abstract-image 13.0.61 → 13.1.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +1 -6
  3. package/lib/__stories__/react-svg-export/example-1.stories.d.ts +2 -2
  4. package/lib/__stories__/react-svg-export/example-1.stories.d.ts.map +1 -1
  5. package/lib/__stories__/react-svg-export/example-1.stories.js.map +1 -1
  6. package/lib/__stories__/svg-export/example-1.stories.d.ts +2 -2
  7. package/lib/__stories__/svg-export/example-1.stories.d.ts.map +1 -1
  8. package/lib/__stories__/svg-export/example-1.stories.js.map +1 -1
  9. package/lib/abstract-image-jsx/index.d.ts +2 -3
  10. package/lib/abstract-image-jsx/index.d.ts.map +1 -1
  11. package/lib/abstract-image-jsx/index.js +11 -8
  12. package/lib/abstract-image-jsx/index.js.map +1 -1
  13. package/lib/dynamic-image/components.d.ts +1 -1
  14. package/lib/dynamic-image/components.d.ts.map +1 -1
  15. package/lib/dynamic-image/components.js +3 -4
  16. package/lib/dynamic-image/components.js.map +1 -1
  17. package/lib/dynamic-image/dynamic-image.d.ts.map +1 -1
  18. package/lib/dynamic-image/dynamic-image.js +2 -4
  19. package/lib/dynamic-image/dynamic-image.js.map +1 -1
  20. package/lib/dynamic-image/utils.d.ts +2 -1
  21. package/lib/dynamic-image/utils.d.ts.map +1 -1
  22. package/lib/dynamic-image/utils.js.map +1 -1
  23. package/lib/exporters/dxf2d-export-image.d.ts +3 -2
  24. package/lib/exporters/dxf2d-export-image.d.ts.map +1 -1
  25. package/lib/exporters/dxf2d-export-image.js +13 -23
  26. package/lib/exporters/dxf2d-export-image.js.map +1 -1
  27. package/lib/exporters/eps-export-image.d.ts +1 -2
  28. package/lib/exporters/eps-export-image.d.ts.map +1 -1
  29. package/lib/exporters/eps-export-image.js +5 -16
  30. package/lib/exporters/eps-export-image.js.map +1 -1
  31. package/lib/exporters/react-svg-export-image.d.ts.map +1 -1
  32. package/lib/exporters/react-svg-export-image.js +10 -10
  33. package/lib/exporters/react-svg-export-image.js.map +1 -1
  34. package/lib/exporters/svg-export-image.d.ts.map +1 -1
  35. package/lib/exporters/svg-export-image.js +7 -5
  36. package/lib/exporters/svg-export-image.js.map +1 -1
  37. package/lib/model/abstract-image.d.ts +1 -1
  38. package/lib/model/abstract-image.d.ts.map +1 -1
  39. package/lib/model/abstract-image.js.map +1 -1
  40. package/lib/model/color.d.ts.map +1 -1
  41. package/lib/model/color.js +3 -5
  42. package/lib/model/color.js.map +1 -1
  43. package/lib/model/component.d.ts +3 -5
  44. package/lib/model/component.d.ts.map +1 -1
  45. package/lib/model/component.js +1 -1
  46. package/lib/model/component.js.map +1 -1
  47. package/package.json +17 -17
  48. package/src/__stories__/react-svg-export/example-1.stories.tsx +4 -14
  49. package/src/__stories__/svg-export/example-1.stories.tsx +4 -15
  50. package/src/abstract-image-jsx/index.ts +27 -32
  51. package/src/dynamic-image/components.ts +6 -19
  52. package/src/dynamic-image/dynamic-image.ts +6 -23
  53. package/src/dynamic-image/utils.ts +7 -5
  54. package/src/exporters/dxf2d-export-image.ts +22 -65
  55. package/src/exporters/eps-export-image.ts +8 -18
  56. package/src/exporters/react-svg-export-image.tsx +24 -49
  57. package/src/exporters/svg-export-image.ts +10 -15
  58. package/src/model/abstract-image.ts +2 -7
  59. package/src/model/color.ts +4 -13
  60. package/src/model/component.ts +5 -13
@@ -8,7 +8,7 @@ import type { Size } from "../model/size.js";
8
8
 
9
9
  export const DXF_STANDARD = "AC1015";
10
10
  export const DXF_DATA_URL = "data:application/dxf,";
11
- export const DXF_ENTITIES: string[] = [
11
+ export const DXF_ENTITIES: Array<string> = [
12
12
  "3DFACE",
13
13
  "3DSOLID",
14
14
  "ACAD_PROXY_ENTITY",
@@ -87,11 +87,13 @@ export function dxf2dExportImageEncoded(root: AbstractImage, options?: Optional<
87
87
  }
88
88
 
89
89
  function encodeWindows1252(str: string): Uint8Array {
90
+ // oxlint-disable-next-line no-bitwise
90
91
  return Uint8Array.from(str, (c) => c.charCodeAt(0) & 0xff);
91
92
  }
92
93
 
93
94
  /**
94
- * @deprecated Use `dxf2dExportImageEncoded()` instead. Otherwise the text might not be correctly encoded in some languages.
95
+ * @deprecated Use `dxf2dExportImageEncoded()` instead. Otherwise the text might not be correctly encoded in some
96
+ * languages.
95
97
  */
96
98
  export function dxf2dExportImage(root: AbstractImage, options?: Optional<DxfOptions>): string {
97
99
  const externalCache = new Map<string, DxfInsert>();
@@ -115,15 +117,7 @@ export function dxf2dExportImage(root: AbstractImage, options?: Optional<DxfOpti
115
117
  blocks += createSpaceBlock("*Model_Space", modelSpaceHandle, newHandle);
116
118
  blocks += createSpaceBlock("*Paper_Space", paperSpaceHandle, newHandle);
117
119
  for (const component of root.components) {
118
- const [newEntities, newBlocks, newBlockRecords] = componentDxf(
119
- component,
120
- layer,
121
- root.size,
122
- modelSpaceHandle,
123
- externalCache,
124
- opts,
125
- newHandle
126
- );
120
+ const [newEntities, newBlocks, newBlockRecords] = componentDxf(component, layer, root.size, modelSpaceHandle, externalCache, opts, newHandle);
127
121
  entities += newEntities;
128
122
  blocks += newBlocks;
129
123
  blockRecords.push(...newBlockRecords);
@@ -192,15 +186,7 @@ function componentDxf(
192
186
 
193
187
  if (c.type === "group") {
194
188
  for (const child of c.children) {
195
- const [newEntities, newBlocks, newBlockRecords] = componentDxf(
196
- child,
197
- layer,
198
- size,
199
- modelSpaceHandle,
200
- externalCache,
201
- options,
202
- newHandle
203
- );
189
+ const [newEntities, newBlocks, newBlockRecords] = componentDxf(child, layer, size, modelSpaceHandle, externalCache, options, newHandle);
204
190
  entities += newEntities;
205
191
  blocks += newBlocks;
206
192
  blockRecords.push(...newBlockRecords);
@@ -214,11 +200,7 @@ function componentDxf(
214
200
  }
215
201
  const imageData = options.imageDataByUrl[c.data.url];
216
202
  const url =
217
- imageData === undefined
218
- ? c.data.url
219
- : typeof imageData === "string"
220
- ? imageData
221
- : DXF_DATA_URL + dxf2dExportImage(imageData, options);
203
+ imageData === undefined ? c.data.url : typeof imageData === "string" ? imageData : DXF_DATA_URL + dxf2dExportImage(imageData, options);
222
204
  if (url === undefined || typeof url !== "string" || !url.startsWith(DXF_DATA_URL)) {
223
205
  return [entities, blocks, blockRecords];
224
206
  }
@@ -253,9 +235,7 @@ function componentDxf(
253
235
  const externalBlockRecords = extractBlockRecords(dxfString);
254
236
 
255
237
  const newBlockRecordHandle = newHandle();
256
- const newName = `EMBEDED_IMAGE_${randomID()}_${scale.x.toPrecision(4).replace(".", "_")}X${scale.y
257
- .toPrecision(4)
258
- .replace(".", "_")}`;
238
+ const newName = `EMBEDED_IMAGE_${randomID()}_${scale.x.toPrecision(4).replace(".", "_")}X${scale.y.toPrecision(4).replace(".", "_")}`;
259
239
 
260
240
  const initOldHandlesMap = new Map<string, string>();
261
241
 
@@ -373,8 +353,8 @@ function componentDxf(
373
353
  entities += "70\n0\n";
374
354
 
375
355
  if (options.useStrokeThickness) {
376
- entities += "40\n" + (c.strokeThickness ?? 0) + "\n";
377
- entities += "41\n" + (c.strokeThickness ?? 0) + "\n";
356
+ entities += "40\n" + c.strokeThickness + "\n";
357
+ entities += "41\n" + c.strokeThickness + "\n";
378
358
  }
379
359
 
380
360
  const points: ReadonlyArray<Point> = [
@@ -422,8 +402,8 @@ function componentDxf(
422
402
  entities += "70\n0\n";
423
403
 
424
404
  if (options.useStrokeThickness) {
425
- entities += "40\n" + (c.strokeThickness ?? 0) + "\n";
426
- entities += "41\n" + (c.strokeThickness ?? 0) + "\n";
405
+ entities += "40\n" + c.strokeThickness + "\n";
406
+ entities += "41\n" + c.strokeThickness + "\n";
427
407
  }
428
408
 
429
409
  for (const point of c.points) {
@@ -448,8 +428,7 @@ function componentDxf(
448
428
  }
449
429
 
450
430
  if (c.type === "text") {
451
- const horizontalAlignment =
452
- c.horizontalGrowthDirection === "left" ? 2 : c.horizontalGrowthDirection === "uniform" ? 1 : 0;
431
+ const horizontalAlignment = c.horizontalGrowthDirection === "left" ? 2 : c.horizontalGrowthDirection === "uniform" ? 1 : 0;
453
432
  const verticalAlignment = c.verticalGrowthDirection === "up" ? 0 : c.verticalGrowthDirection === "uniform" ? 2 : 3;
454
433
  const fontSize = c.fontSize - 2;
455
434
 
@@ -618,9 +597,7 @@ function extractEntities(dxf: string): string | undefined {
618
597
  }
619
598
 
620
599
  function extractBlockRecords(dxf: string): ReadonlyArray<BlockRecord> {
621
- return [
622
- ...dxf.matchAll(/^\s*0\s*\n\s*BLOCK_RECORD[\s\S]*?\n\s*5\s*\n\s*([0-9A-Fa-f]+)[\s\S]*?\n\s*2\s*\n\s*([^\r\n]+)/gm),
623
- ].map((match) => ({
600
+ return [...dxf.matchAll(/^\s*0\s*\n\s*BLOCK_RECORD[\s\S]*?\n\s*5\s*\n\s*([0-9A-Fa-f]+)[\s\S]*?\n\s*2\s*\n\s*([^\r\n]+)/gm)].map((match) => ({
624
601
  name: match[2],
625
602
  id: match[1],
626
603
  }));
@@ -676,7 +653,7 @@ function remapHandleIds(
676
653
 
677
654
  function collectAndRemap(src: string): string {
678
655
  const lines = src.split("\n");
679
- const out: string[] = [];
656
+ const out: Array<string> = [];
680
657
  let i = 0;
681
658
  let inEntityHeader = false;
682
659
  while (i < lines.length) {
@@ -727,7 +704,7 @@ function scaleDxf(dxfString: string | undefined, sx: number, sy: number, _height
727
704
  const yCoordinateCodes = new Set([20, 21, 22, 23, 24, 25, 26, 27, 28]);
728
705
 
729
706
  const lines = dxfString.split(/\r?\n/);
730
- const scaledLines: string[] = [];
707
+ const scaledLines: Array<string> = [];
731
708
 
732
709
  let currentAcDbEntity = "";
733
710
  for (let i = 0; i < lines.length; i += 2) {
@@ -739,9 +716,6 @@ function scaleDxf(dxfString: string | undefined, sx: number, sy: number, _height
739
716
  }
740
717
 
741
718
  scaledLines.push(codeLine);
742
- if (valueLine === undefined) {
743
- continue;
744
- }
745
719
 
746
720
  const code = parseInt(codeLine.trim(), 10);
747
721
  let value = valueLine;
@@ -816,13 +790,7 @@ function getScale(extents: DxfExtents, c: BinaryImage): { readonly x: number; re
816
790
  };
817
791
  }
818
792
 
819
- function createExternalInsert(
820
- ins: DxfInsert,
821
- c: BinaryImage,
822
- size: Size,
823
- modelSpaceHandle: string,
824
- newHandle: () => string
825
- ): string {
793
+ function createExternalInsert(ins: DxfInsert, c: BinaryImage, size: Size, modelSpaceHandle: string, newHandle: () => string): string {
826
794
  const srcH = ins.extents.maxY - ins.extents.minY;
827
795
  const srcW = ins.extents.maxX - ins.extents.minX;
828
796
  const destW = c.bottomRight.x - c.topLeft.x;
@@ -1006,12 +974,7 @@ function createStyleTable(newHandle: () => string): string {
1006
974
  return table;
1007
975
  }
1008
976
 
1009
- function createDimStyleTable(
1010
- newHandle: () => string,
1011
- dimArrowSize: number = 1.0,
1012
- dimGlobalScale: number = 1.0,
1013
- dimFontSize: number = 1.0
1014
- ): string {
977
+ function createDimStyleTable(newHandle: () => string, dimArrowSize: number = 1.0, dimGlobalScale: number = 1.0, dimFontSize: number = 1.0): string {
1015
978
  const rootId = newHandle();
1016
979
  let table = "";
1017
980
  table += "0\nTABLE\n";
@@ -1129,12 +1092,7 @@ function createBlockRecordsTable(
1129
1092
  return table;
1130
1093
  }
1131
1094
 
1132
- function createObjects(
1133
- modelSpaceHandle: string,
1134
- paperSpaceHandle: string,
1135
- root: AbstractImage,
1136
- newHandle: () => string
1137
- ): string {
1095
+ function createObjects(modelSpaceHandle: string, paperSpaceHandle: string, root: AbstractImage, newHandle: () => string): string {
1138
1096
  let objects = "";
1139
1097
  const rootDictId = newHandle();
1140
1098
  const groupDictId = newHandle();
@@ -1161,8 +1119,7 @@ function createObjects(
1161
1119
  objects += "0\nLAYOUT\n5\n" + layoutModelId + "\n102\n{ACAD_REACTORS\n330\n" + layoutDictId + "\n102\n}\n";
1162
1120
  objects += "330\n" + layoutDictId + "\n100\nAcDbPlotSettings\n1\n\n2\nnone_device\n4\n\n6\n\n";
1163
1121
  objects += "40\n0.0\n41\n0.0\n42\n0.0\n43\n0.0\n44\n0.0\n45\n0.0\n46\n0.0\n47\n0.0\n48\n0.0\n49\n0.0\n";
1164
- objects +=
1165
- "140\n0.0\n141\n0.0\n142\n1.0\n143\n1.0\n70\n1712\n72\n0\n73\n0\n74\n0\n7\n\n75\n0\n147\n1.0\n148\n0.0\n149\n0.0\n";
1122
+ objects += "140\n0.0\n141\n0.0\n142\n1.0\n143\n1.0\n70\n1712\n72\n0\n73\n0\n74\n0\n7\n\n75\n0\n147\n1.0\n148\n0.0\n149\n0.0\n";
1166
1123
  objects += "100\nAcDbLayout\n1\nModel\n70\n1\n71\n0\n";
1167
1124
  objects += "10\n0.0\n20\n0.0\n11\n" + root.size.width + "\n21\n" + root.size.height + "\n";
1168
1125
  objects += "12\n0.0\n22\n0.0\n32\n0.0\n14\n0.0\n24\n0.0\n34\n0.0\n";
@@ -1174,8 +1131,7 @@ function createObjects(
1174
1131
  objects += "0\nLAYOUT\n5\n" + layoutPaperId + "\n102\n{ACAD_REACTORS\n330\n" + layoutDictId + "\n102\n}\n";
1175
1132
  objects += "330\n" + layoutDictId + "\n100\nAcDbPlotSettings\n1\n\n2\nnone_device\n4\n\n6\n\n";
1176
1133
  objects += "40\n0.0\n41\n0.0\n42\n0.0\n43\n0.0\n44\n0.0\n45\n0.0\n46\n0.0\n47\n0.0\n48\n0.0\n49\n0.0\n";
1177
- objects +=
1178
- "140\n0.0\n141\n0.0\n142\n1.0\n143\n1.0\n70\n688\n72\n0\n73\n0\n74\n5\n7\n\n75\n16\n147\n1.0\n148\n0.0\n149\n0.0\n";
1134
+ objects += "140\n0.0\n141\n0.0\n142\n1.0\n143\n1.0\n70\n688\n72\n0\n73\n0\n74\n5\n7\n\n75\n16\n147\n1.0\n148\n0.0\n149\n0.0\n";
1179
1135
  objects += "100\nAcDbLayout\n1\nLayout1\n70\n1\n71\n1\n";
1180
1136
  objects += "10\n0.0\n20\n0.0\n11\n" + root.size.width + "\n21\n" + root.size.height + "\n";
1181
1137
  objects += "12\n0.0\n22\n0.0\n32\n0.0\n14\n1.0E+20\n24\n1.0E+20\n34\n1.0E+20\n";
@@ -1339,6 +1295,7 @@ function isBlack(color: Color): boolean {
1339
1295
  }
1340
1296
 
1341
1297
  function colorToInteger(color: Color): number {
1298
+ // oxlint-disable-next-line no-bitwise
1342
1299
  const colorAsInt = (color.r << 16) + (color.g << 8) + color.b;
1343
1300
  if (Number.isNaN(colorAsInt)) {
1344
1301
  return 0;
@@ -4,8 +4,7 @@ import type { Component, Text } from "../model/component.js";
4
4
 
5
5
  type CharacterEncoding = "standard-encoding" | "iso-latin-1-encoding";
6
6
 
7
- export function epsExportImage(root: AbstractImage): string;
8
- export function epsExportImage(root: AbstractImage, characterEncoding: "standard-encoding"): string;
7
+ export function epsExportImage(root: AbstractImage, characterEncoding?: "standard-encoding"): string;
9
8
  export function epsExportImage(root: AbstractImage, characterEncoding: "iso-latin-1-encoding"): Uint8Array;
10
9
  export function epsExportImage(root: AbstractImage, characterEncoding?: CharacterEncoding): string | Uint8Array {
11
10
  if (characterEncoding === "iso-latin-1-encoding") {
@@ -16,10 +15,9 @@ export function epsExportImage(root: AbstractImage, characterEncoding?: Characte
16
15
  ].join("\n");
17
16
  return encodeLatin1Encoding(eps);
18
17
  } else {
19
- return [
20
- ...createEpsHeaderLines(root),
21
- ...root.components.flatMap((c) => epsExportComponent(c, root.size.height, "standard-encoding")),
22
- ].join("\n");
18
+ return [...createEpsHeaderLines(root), ...root.components.flatMap((c) => epsExportComponent(c, root.size.height, "standard-encoding"))].join(
19
+ "\n"
20
+ );
23
21
  }
24
22
  }
25
23
 
@@ -53,12 +51,7 @@ function epsExportComponent(c: Component, height: number, characterEncoding: Cha
53
51
  const ry = 0.5 * (c.bottomRight.y - c.topLeft.y);
54
52
  return [
55
53
  ...getColored(c.fillColor, [`${cx} ${cy} ${rx} ${ry} 0 360 ellipse`, "closepath", "fill"]),
56
- ...getColored(c.strokeColor, [
57
- `${cx} ${cy} ${rx} ${ry} 0 360 ellipse`,
58
- "closepath",
59
- `${c.strokeThickness} setlinewidth`,
60
- "stroke",
61
- ]),
54
+ ...getColored(c.strokeColor, [`${cx} ${cy} ${rx} ${ry} 0 360 ellipse`, "closepath", `${c.strokeThickness} setlinewidth`, "stroke"]),
62
55
  ];
63
56
  }
64
57
  case "group": {
@@ -102,10 +95,7 @@ function epsExportComponent(c: Component, height: number, characterEncoding: Cha
102
95
  const h = c.bottomRight.y - c.topLeft.y;
103
96
  return [
104
97
  ...getColored(c.fillColor, [`${c.topLeft.x} ${height - c.bottomRight.y} ${w} ${h} rectfill`]),
105
- ...getColored(c.strokeColor, [
106
- `${c.strokeThickness} setlinewidth`,
107
- `${c.topLeft.x} ${height - c.bottomRight.y} ${w} ${h} rectstroke`,
108
- ]),
98
+ ...getColored(c.strokeColor, [`${c.strokeThickness} setlinewidth`, `${c.topLeft.x} ${height - c.bottomRight.y} ${w} ${h} rectstroke`]),
109
99
  ];
110
100
  }
111
101
  case "text": {
@@ -165,14 +155,14 @@ function createFontName(characterEncoding: CharacterEncoding, fontFamily: string
165
155
  function encodeLatin1Encoding(text: string): Uint8Array {
166
156
  // ISOLatin1Encoding is close to iso-8859-1 encoding (https://en.wikipedia.org/wiki/PostScript_Latin_1_Encoding)
167
157
  // Code points 0-256 returned by codePointAt() maps to iso-8859-1
168
- const unknownCharacter = "?".codePointAt(0) || 32;
158
+ const unknownCharacter = "?".codePointAt(0) ?? 32;
169
159
  const output: Array<number> = [];
170
160
  // Array.from() to handle characters consisting of multiple code points
171
161
  for (const c of Array.from(text)) {
172
162
  if (c.length > 1) {
173
163
  output.push(unknownCharacter);
174
164
  } else {
175
- const cp = c.codePointAt(0) || 32;
165
+ const cp = c.codePointAt(0) ?? 32;
176
166
  if (cp > 255) {
177
167
  output.push(unknownCharacter);
178
168
  }
@@ -1,10 +1,10 @@
1
1
  import { fromByteArray } from "base64-js";
2
2
  import React from "react";
3
3
  import type { AbstractImage } from "../model/abstract-image.js";
4
+ import type { Color } from "../model/color.js";
5
+ import type { AbstractFontWeight, Component, GrowthDirection } from "../model/component.js";
4
6
  import type { Point } from "../model/point.js";
5
7
  import { createPoint } from "../model/point.js";
6
- import type { AbstractFontWeight, Component, GrowthDirection } from "../model/component.js";
7
- import type { Color } from "../model/color.js";
8
8
  import type { Optional } from "../model/shared.js";
9
9
 
10
10
  export interface ReactSvgCallbacks {
@@ -32,7 +32,7 @@ export function ReactSvg({
32
32
  const opts: ReactSvgOptions = {
33
33
  imageDataByUrl: options?.imageDataByUrl ?? {},
34
34
  };
35
- const cb = callbacks || {};
35
+ const cb = callbacks ?? {};
36
36
  const id = "ai_root";
37
37
  return (
38
38
  <svg
@@ -85,13 +85,7 @@ function getIdAttr(target: Element | undefined, rootId: string): string | undefi
85
85
  return parts[1];
86
86
  }
87
87
 
88
- function JsxComponent({
89
- component,
90
- options,
91
- }: {
92
- readonly component: Component;
93
- readonly options: ReactSvgOptions;
94
- }): React.JSX.Element {
88
+ function JsxComponent({ component, options }: { readonly component: Component; readonly options: ReactSvgOptions }): React.JSX.Element {
95
89
  switch (component.type) {
96
90
  case "group":
97
91
  return (
@@ -109,8 +103,8 @@ function JsxComponent({
109
103
  const id = makeIdAttr(component.id);
110
104
  if (component.data.type === "url") {
111
105
  const data = options.imageDataByUrl[component.data.url];
112
- if (typeof data === "string" || data === undefined) {
113
- return <image x={x} y={y} width={width} height={height} id={id} href={data ?? component.data.url} />;
106
+ if (typeof data === "string") {
107
+ return <image x={x} y={y} width={width} height={height} id={id} href={data} />;
114
108
  }
115
109
  const scale = Math.min(width / (data.size.width || 1), height / (data.size.height || 1));
116
110
  return (
@@ -145,10 +139,8 @@ function JsxComponent({
145
139
  );
146
140
  }
147
141
  case "line": {
148
- const strokeDasharray =
149
- component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.dashes.join(" ") : undefined;
150
- const strokeDashoffset =
151
- component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.offset : undefined;
142
+ const strokeDasharray = component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.dashes.join(" ") : undefined;
143
+ const strokeDashoffset = component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.offset : undefined;
152
144
  return (
153
145
  <line
154
146
  id={makeIdAttr(component.id)}
@@ -171,7 +163,7 @@ function JsxComponent({
171
163
  }
172
164
  const alignmentBaseline = getBaselineAdjustment(component.verticalGrowthDirection);
173
165
  const transform = `rotate(${component.clockwiseRotationDegrees} ${component.position.x} ${component.position.y})`;
174
- const lines: Array<string> = component.text !== null ? component.text.split("\n") : [];
166
+ const lines = component.text.split("\n");
175
167
  const tSpans = lines.map((t, i) => (
176
168
  <TSpan
177
169
  key={t}
@@ -192,7 +184,7 @@ function JsxComponent({
192
184
  };
193
185
  return (
194
186
  <>
195
- {component.strokeThickness > 0 && component.strokeColor && (
187
+ {component.strokeThickness > 0 && (
196
188
  <text
197
189
  style={{
198
190
  ...baseStyle,
@@ -205,11 +197,7 @@ function JsxComponent({
205
197
  {tSpans}
206
198
  </text>
207
199
  )}
208
- <text
209
- style={{ ...baseStyle, fill: colorToRgb(component.textColor) }}
210
- transform={transform}
211
- id={makeIdAttr(component.id)}
212
- >
200
+ <text style={{ ...baseStyle, fill: colorToRgb(component.textColor) }} transform={transform} id={makeIdAttr(component.id)}>
213
201
  {tSpans}
214
202
  </text>
215
203
  </>
@@ -220,10 +208,8 @@ function JsxComponent({
220
208
  const ry = Math.abs(component.bottomRight.y - component.topLeft.y) * 0.5;
221
209
  const cx = (component.bottomRight.x + component.topLeft.x) * 0.5;
222
210
  const cy = (component.bottomRight.y + component.topLeft.y) * 0.5;
223
- const strokeDasharray =
224
- component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.dashes.join(" ") : undefined;
225
- const strokeDashoffset =
226
- component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.offset : undefined;
211
+ const strokeDasharray = component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.dashes.join(" ") : undefined;
212
+ const strokeDashoffset = component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.offset : undefined;
227
213
  return (
228
214
  <ellipse
229
215
  id={makeIdAttr(component.id)}
@@ -242,11 +228,9 @@ function JsxComponent({
242
228
  );
243
229
  }
244
230
  case "polyline": {
245
- let linePoints = component.points.map((p) => p.x.toString() + "," + p.y.toString()).join(" ");
246
- const strokeDasharray =
247
- component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.dashes.join(" ") : undefined;
248
- const strokeDashoffset =
249
- component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.offset : undefined;
231
+ const linePoints = component.points.map((p) => p.x.toString() + "," + p.y.toString()).join(" ");
232
+ const strokeDasharray = component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.dashes.join(" ") : undefined;
233
+ const strokeDashoffset = component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.offset : undefined;
250
234
  return (
251
235
  <polyline
252
236
  id={makeIdAttr(component.id)}
@@ -263,11 +247,9 @@ function JsxComponent({
263
247
  );
264
248
  }
265
249
  case "polygon": {
266
- let points = component.points.map((p) => p.x.toString() + "," + p.y.toString()).join(" ");
267
- const strokeDasharray =
268
- component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.dashes.join(" ") : undefined;
269
- const strokeDashoffset =
270
- component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.offset : undefined;
250
+ const points = component.points.map((p) => p.x.toString() + "," + p.y.toString()).join(" ");
251
+ const strokeDasharray = component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.dashes.join(" ") : undefined;
252
+ const strokeDashoffset = component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.offset : undefined;
271
253
  return (
272
254
  <polygon
273
255
  id={makeIdAttr(component.id)}
@@ -284,10 +266,8 @@ function JsxComponent({
284
266
  );
285
267
  }
286
268
  case "rectangle": {
287
- const strokeDasharray =
288
- component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.dashes.join(" ") : undefined;
289
- const strokeDashoffset =
290
- component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.offset : undefined;
269
+ const strokeDasharray = component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.dashes.join(" ") : undefined;
270
+ const strokeDashoffset = component.strokeDashStyle.dashes.length > 0 ? component.strokeDashStyle.offset : undefined;
291
271
  return (
292
272
  <rect
293
273
  id={makeIdAttr(component.id)}
@@ -343,12 +323,7 @@ function TSpan({
343
323
  const splitText = split[i];
344
324
  if (inside) {
345
325
  tags.push(
346
- <tspan
347
- key={i}
348
- baselineShift="sub"
349
- alignmentBaseline={alignmentBaseline}
350
- style={{ fontSize: (fontSize * 0.8).toString() + "px" }}
351
- >
326
+ <tspan key={i} baselineShift="sub" alignmentBaseline={alignmentBaseline} style={{ fontSize: (fontSize * 0.8).toString() + "px" }}>
352
327
  {splitText}
353
328
  </tspan>
354
329
  );
@@ -378,7 +353,7 @@ function getBaselineAdjustment(d: GrowthDirection): "baseline" | "central" | "ha
378
353
  if (d === "down") {
379
354
  return "hanging";
380
355
  }
381
- throw "Unknown text alignment " + d;
356
+ throw new Error("Unknown text alignment " + d);
382
357
  }
383
358
 
384
359
  function getTextAnchor(d: GrowthDirection): "end" | "middle" | "start" {
@@ -391,7 +366,7 @@ function getTextAnchor(d: GrowthDirection): "end" | "middle" | "start" {
391
366
  if (d === "right") {
392
367
  return "start";
393
368
  }
394
- throw "Unknown text anchor " + d;
369
+ throw new Error("Unknown text anchor " + d);
395
370
  }
396
371
 
397
372
  function colorToRgb(color: Color): string {
@@ -1,7 +1,7 @@
1
1
  import { fromByteArray } from "base64-js";
2
- import type { Component, GrowthDirection } from "../model/component.js";
3
2
  import type { AbstractImage } from "../model/abstract-image.js";
4
3
  import type { Color } from "../model/color.js";
4
+ import type { Component, GrowthDirection } from "../model/component.js";
5
5
  import type { Optional } from "../model/shared.js";
6
6
 
7
7
  export const SVG_DATA_URL = "data:image/svg+xml,";
@@ -15,8 +15,8 @@ export type SvgOptions = {
15
15
  export function createSVG(image: AbstractImage, options?: Optional<SvgOptions>): string {
16
16
  const opts: SvgOptions = {
17
17
  imageDataByUrl: options?.imageDataByUrl ?? {},
18
- pixelWidth: options?.pixelWidth || image.size.width,
19
- pixelHeight: options?.pixelHeight || image.size.height,
18
+ pixelWidth: options?.pixelWidth ?? image.size.width,
19
+ pixelHeight: options?.pixelHeight ?? image.size.height,
20
20
  };
21
21
  const subOptions: SvgOptions = { ...opts, pixelWidth: 0, pixelHeight: 0 };
22
22
  const imageElements = image.components.map((c: Component) => abstractComponentToSVG(c, subOptions));
@@ -75,15 +75,10 @@ function abstractComponentToSVG(component: Component, options: SvgOptions): stri
75
75
  return "";
76
76
  }
77
77
  case "subimage": {
78
- const scale = Math.min(
79
- component.size.width / (component.image.size.width || 1),
80
- component.size.height / (component.image.size.height || 1)
81
- );
82
- return createElement(
83
- "g",
84
- { transform: `translate(${component.topLeft.x}, ${component.topLeft.y}) scale(${scale})` },
85
- [createSVG(component.image, { ...options, pixelWidth: undefined, pixelHeight: undefined })]
86
- );
78
+ const scale = Math.min(component.size.width / (component.image.size.width || 1), component.size.height / (component.image.size.height || 1));
79
+ return createElement("g", { transform: `translate(${component.topLeft.x}, ${component.topLeft.y}) scale(${scale})` }, [
80
+ createSVG(component.image, { ...options, pixelWidth: undefined, pixelHeight: undefined }),
81
+ ]);
87
82
  }
88
83
  case "line": {
89
84
  const dashStyle: Attributes =
@@ -297,7 +292,7 @@ interface Attributes {
297
292
  readonly [key: string]: string;
298
293
  }
299
294
 
300
- function createElement(elementName: string, attributes: Attributes, innerElements: string[]): string {
295
+ function createElement(elementName: string, attributes: Attributes, innerElements: Array<string>): string {
301
296
  const formattedName = convertUpperToHyphenLower(elementName);
302
297
  let element = `<${formattedName}`;
303
298
 
@@ -360,7 +355,7 @@ function getBaselineAdjustment(d: GrowthDirection): "baseline" | "central" | "ha
360
355
  if (d === "down") {
361
356
  return "hanging";
362
357
  }
363
- throw "Unknown text alignment " + d;
358
+ throw new Error("Unknown text alignment " + d);
364
359
  }
365
360
 
366
361
  function getTextAnchor(d: GrowthDirection): string {
@@ -373,7 +368,7 @@ function getTextAnchor(d: GrowthDirection): string {
373
368
  if (d === "right") {
374
369
  return "start";
375
370
  }
376
- throw "Unknown text anchor " + d;
371
+ throw new Error("Unknown text anchor " + d);
377
372
  }
378
373
 
379
374
  function colorToRgb(color: Color): string {
@@ -1,7 +1,7 @@
1
- import type { Size } from "./size.js";
2
1
  import type { Color } from "./color.js";
3
2
  import type { Component } from "./component.js";
4
3
  import type { Point } from "./point.js";
4
+ import type { Size } from "./size.js";
5
5
 
6
6
  export interface AbstractImage {
7
7
  readonly topLeft: Point;
@@ -10,12 +10,7 @@ export interface AbstractImage {
10
10
  readonly components: Array<Component>;
11
11
  }
12
12
 
13
- export function createAbstractImage(
14
- topLeft: Point,
15
- size: Size,
16
- backgroundColor: Color,
17
- components: Array<Component>
18
- ): AbstractImage {
13
+ export function createAbstractImage(topLeft: Point, size: Size, backgroundColor: Color, components: Array<Component>): AbstractImage {
19
14
  return {
20
15
  topLeft: topLeft,
21
16
  size: size,
@@ -10,15 +10,11 @@ export function fromArgb(a: number, r: number, g: number, b: number): Color {
10
10
  }
11
11
 
12
12
  export function toString6Hex(color: Color): string {
13
- return (
14
- ("00" + color.r.toString(16)).substr(-2) +
15
- ("00" + color.g.toString(16)).substr(-2) +
16
- ("00" + color.b.toString(16)).substr(-2)
17
- );
13
+ return ("00" + color.r.toString(16)).substr(-2) + ("00" + color.g.toString(16)).substr(-2) + ("00" + color.b.toString(16)).substr(-2);
18
14
  }
19
15
 
20
16
  export function fromString(s: string): Color | undefined {
21
- if (s === null || s === undefined || s.length !== 9 || s[0] !== "#") {
17
+ if (s?.length !== 9 || !s.startsWith("#")) {
22
18
  return undefined;
23
19
  }
24
20
 
@@ -27,7 +23,7 @@ export function fromString(s: string): Color | undefined {
27
23
  const g: number = parseInt(s.substring(5, 5 + 2), 16);
28
24
  const b: number = parseInt(s.substring(7, 7 + 2), 16);
29
25
 
30
- if (isNaN(a) || isNaN(r) || isNaN(g) || isNaN(b)) {
26
+ if (Number.isNaN(a) || Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) {
31
27
  return undefined;
32
28
  }
33
29
 
@@ -37,12 +33,7 @@ export function fromString(s: string): Color | undefined {
37
33
  export function fromString2(s: string, def?: Color): Color {
38
34
  if (s.startsWith("#")) {
39
35
  if (s.length === 9) {
40
- return fromArgb(
41
- parseInt(s.slice(1, 3), 16),
42
- parseInt(s.slice(3, 5), 16),
43
- parseInt(s.slice(5, 7), 16),
44
- parseInt(s.slice(7, 9), 16)
45
- );
36
+ return fromArgb(parseInt(s.slice(1, 3), 16), parseInt(s.slice(3, 5), 16), parseInt(s.slice(5, 7), 16), parseInt(s.slice(7, 9), 16));
46
37
  }
47
38
  return fromArgb(255, parseInt(s.slice(1, 3), 16), parseInt(s.slice(3, 5), 16), parseInt(s.slice(5, 7), 16));
48
39
  }
@@ -1,9 +1,9 @@
1
- import type { Point } from "./point.js";
2
- import { createPoint } from "./point.js";
1
+ import type { AbstractImage } from "./abstract-image.js";
3
2
  import type { Color } from "./color.js";
4
3
  import type { DashStyle } from "./dash-style.js";
5
4
  import { solidLine } from "./dash-style.js";
6
- import type { AbstractImage } from "./abstract-image.js";
5
+ import type { Point } from "./point.js";
6
+ import { createPoint } from "./point.js";
7
7
  import type { Size } from "./size.js";
8
8
 
9
9
  export type Component = BinaryImage | Ellipse | Line | PolyLine | Polygon | Rectangle | Text | SubImage | Group;
@@ -22,9 +22,7 @@ export function createGroup(name: string, children: Array<Component>): Group {
22
22
  };
23
23
  }
24
24
 
25
- /**
26
- * Embed a foreign binary image in any suported format.
27
- */
25
+ /** Embed a foreign binary image in any suported format. */
28
26
 
29
27
  export type BinaryFormat = "svg" | "png" | "dxf";
30
28
 
@@ -49,13 +47,7 @@ export interface ImageUrl {
49
47
  readonly url: string;
50
48
  }
51
49
 
52
- export function createBinaryImage(
53
- topLeft: Point,
54
- bottomRight: Point,
55
- format: BinaryFormat,
56
- data: ImageData,
57
- id?: string
58
- ): BinaryImage {
50
+ export function createBinaryImage(topLeft: Point, bottomRight: Point, format: BinaryFormat, data: ImageData, id?: string): BinaryImage {
59
51
  return {
60
52
  type: "binaryimage",
61
53
  topLeft: topLeft,