@linkiez/dxf-renew 7.0.0 → 7.2.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 (252) hide show
  1. package/.eslintrc.json +1 -16
  2. package/.github/instructions/code-patterns.instructions.md +1 -1
  3. package/.github/instructions/exdxf.instruction.md +161 -0
  4. package/.github/instructions/tdd.instructions.md +271 -0
  5. package/.yarn/install-state.gz +0 -0
  6. package/ARCHITECTURE.md +163 -0
  7. package/CHANGELOG.md +39 -0
  8. package/CONTRIBUTING.md +16 -14
  9. package/README.md +113 -16
  10. package/{PLAN.md → ROADMAP.md} +244 -102
  11. package/dist/dxf.js +2212 -454
  12. package/docs/EZDXF_REFERENCE_SITEMAP.md +55 -0
  13. package/docs/FIXTURE_VALIDATION_EZDXF.md +62 -0
  14. package/lib/Helper.cjs +6 -2
  15. package/lib/Helper.cjs.map +3 -3
  16. package/lib/Helper.js +6 -2
  17. package/lib/Helper.js.map +2 -2
  18. package/lib/denormalise.cjs +131 -91
  19. package/lib/denormalise.cjs.map +2 -2
  20. package/lib/denormalise.js +131 -91
  21. package/lib/denormalise.js.map +2 -2
  22. package/lib/dimensionToSVG.cjs +318 -53
  23. package/lib/dimensionToSVG.cjs.map +3 -3
  24. package/lib/dimensionToSVG.js +316 -52
  25. package/lib/dimensionToSVG.js.map +2 -2
  26. package/lib/entityToPolyline.cjs +95 -0
  27. package/lib/entityToPolyline.cjs.map +3 -3
  28. package/lib/entityToPolyline.js +95 -0
  29. package/lib/entityToPolyline.js.map +2 -2
  30. package/lib/handlers/entities.cjs +111 -27
  31. package/lib/handlers/entities.cjs.map +3 -3
  32. package/lib/handlers/entities.js +111 -27
  33. package/lib/handlers/entities.js.map +3 -3
  34. package/lib/handlers/entity/dgnUnderlay.cjs +106 -0
  35. package/lib/handlers/entity/dgnUnderlay.cjs.map +7 -0
  36. package/lib/handlers/entity/dgnUnderlay.js +71 -0
  37. package/lib/handlers/entity/dgnUnderlay.js.map +7 -0
  38. package/lib/handlers/entity/dimension.cjs +24 -0
  39. package/lib/handlers/entity/dimension.cjs.map +2 -2
  40. package/lib/handlers/entity/dimension.js +24 -0
  41. package/lib/handlers/entity/dimension.js.map +2 -2
  42. package/lib/handlers/entity/dwfUnderlay.cjs +106 -0
  43. package/lib/handlers/entity/dwfUnderlay.cjs.map +7 -0
  44. package/lib/handlers/entity/dwfUnderlay.js +71 -0
  45. package/lib/handlers/entity/dwfUnderlay.js.map +7 -0
  46. package/lib/handlers/entity/image.cjs +123 -0
  47. package/lib/handlers/entity/image.cjs.map +7 -0
  48. package/lib/handlers/entity/image.js +88 -0
  49. package/lib/handlers/entity/image.js.map +7 -0
  50. package/lib/handlers/entity/leader.cjs +148 -0
  51. package/lib/handlers/entity/leader.cjs.map +7 -0
  52. package/lib/handlers/entity/leader.js +113 -0
  53. package/lib/handlers/entity/leader.js.map +7 -0
  54. package/lib/handlers/entity/mleader.cjs +69 -0
  55. package/lib/handlers/entity/mleader.cjs.map +7 -0
  56. package/lib/handlers/entity/mleader.js +34 -0
  57. package/lib/handlers/entity/mleader.js.map +7 -0
  58. package/lib/handlers/entity/mline.cjs +91 -0
  59. package/lib/handlers/entity/mline.cjs.map +7 -0
  60. package/lib/handlers/entity/mline.js +56 -0
  61. package/lib/handlers/entity/mline.js.map +7 -0
  62. package/lib/handlers/entity/oleframe.cjs +98 -0
  63. package/lib/handlers/entity/oleframe.cjs.map +7 -0
  64. package/lib/handlers/entity/oleframe.js +63 -0
  65. package/lib/handlers/entity/oleframe.js.map +7 -0
  66. package/lib/handlers/entity/pdfUnderlay.cjs +106 -0
  67. package/lib/handlers/entity/pdfUnderlay.cjs.map +7 -0
  68. package/lib/handlers/entity/pdfUnderlay.js +71 -0
  69. package/lib/handlers/entity/pdfUnderlay.js.map +7 -0
  70. package/lib/handlers/entity/ray.cjs +81 -0
  71. package/lib/handlers/entity/ray.cjs.map +7 -0
  72. package/lib/handlers/entity/ray.js +46 -0
  73. package/lib/handlers/entity/ray.js.map +7 -0
  74. package/lib/handlers/entity/region.cjs +67 -0
  75. package/lib/handlers/entity/region.cjs.map +7 -0
  76. package/lib/handlers/entity/region.js +32 -0
  77. package/lib/handlers/entity/region.js.map +7 -0
  78. package/lib/handlers/entity/shape.cjs +95 -0
  79. package/lib/handlers/entity/shape.cjs.map +7 -0
  80. package/lib/handlers/entity/shape.js +60 -0
  81. package/lib/handlers/entity/shape.js.map +7 -0
  82. package/lib/handlers/entity/table.cjs +71 -0
  83. package/lib/handlers/entity/table.cjs.map +7 -0
  84. package/lib/handlers/entity/table.js +36 -0
  85. package/lib/handlers/entity/table.js.map +7 -0
  86. package/lib/handlers/entity/tolerance.cjs +90 -0
  87. package/lib/handlers/entity/tolerance.cjs.map +7 -0
  88. package/lib/handlers/entity/tolerance.js +55 -0
  89. package/lib/handlers/entity/tolerance.js.map +7 -0
  90. package/lib/handlers/entity/trace.cjs +101 -0
  91. package/lib/handlers/entity/trace.cjs.map +7 -0
  92. package/lib/handlers/entity/trace.js +66 -0
  93. package/lib/handlers/entity/trace.js.map +7 -0
  94. package/lib/handlers/entity/wipeout.cjs +122 -0
  95. package/lib/handlers/entity/wipeout.cjs.map +7 -0
  96. package/lib/handlers/entity/wipeout.js +87 -0
  97. package/lib/handlers/entity/wipeout.js.map +7 -0
  98. package/lib/handlers/entity/xline.cjs +81 -0
  99. package/lib/handlers/entity/xline.cjs.map +7 -0
  100. package/lib/handlers/entity/xline.js +46 -0
  101. package/lib/handlers/entity/xline.js.map +7 -0
  102. package/lib/handlers/objects.cjs +299 -136
  103. package/lib/handlers/objects.cjs.map +2 -2
  104. package/lib/handlers/objects.js +299 -136
  105. package/lib/handlers/objects.js.map +2 -2
  106. package/lib/handlers/tables.cjs +96 -17
  107. package/lib/handlers/tables.cjs.map +2 -2
  108. package/lib/handlers/tables.js +96 -17
  109. package/lib/handlers/tables.js.map +2 -2
  110. package/lib/index.cjs +5 -2
  111. package/lib/index.cjs.map +3 -3
  112. package/lib/index.js +18 -16
  113. package/lib/index.js.map +3 -3
  114. package/lib/toJson.cjs +29 -0
  115. package/lib/toJson.cjs.map +7 -0
  116. package/lib/toJson.js +9 -0
  117. package/lib/toJson.js.map +7 -0
  118. package/lib/toSVG.cjs +105 -11
  119. package/lib/toSVG.cjs.map +3 -3
  120. package/lib/toSVG.js +106 -12
  121. package/lib/toSVG.js.map +2 -2
  122. package/lib/types/dimension-entity.cjs.map +1 -1
  123. package/lib/types/entity.cjs.map +1 -1
  124. package/lib/types/helper.cjs.map +1 -1
  125. package/lib/types/image-entity.cjs +17 -0
  126. package/lib/types/image-entity.cjs.map +7 -0
  127. package/lib/types/image-entity.js +1 -0
  128. package/lib/types/image-entity.js.map +7 -0
  129. package/lib/types/index.cjs +28 -0
  130. package/lib/types/index.cjs.map +2 -2
  131. package/lib/types/index.js +14 -0
  132. package/lib/types/index.js.map +2 -2
  133. package/lib/types/leader-entity.cjs +17 -0
  134. package/lib/types/leader-entity.cjs.map +7 -0
  135. package/lib/types/leader-entity.js +1 -0
  136. package/lib/types/leader-entity.js.map +7 -0
  137. package/lib/types/mleader-entity.cjs +17 -0
  138. package/lib/types/mleader-entity.cjs.map +7 -0
  139. package/lib/types/mleader-entity.js +1 -0
  140. package/lib/types/mleader-entity.js.map +7 -0
  141. package/lib/types/mline-entity.cjs +17 -0
  142. package/lib/types/mline-entity.cjs.map +7 -0
  143. package/lib/types/mline-entity.js +1 -0
  144. package/lib/types/mline-entity.js.map +7 -0
  145. package/lib/types/oleframe-entity.cjs +17 -0
  146. package/lib/types/oleframe-entity.cjs.map +7 -0
  147. package/lib/types/oleframe-entity.js +1 -0
  148. package/lib/types/oleframe-entity.js.map +7 -0
  149. package/lib/types/options.cjs.map +1 -1
  150. package/lib/types/ray-entity.cjs +17 -0
  151. package/lib/types/ray-entity.cjs.map +7 -0
  152. package/lib/types/ray-entity.js +1 -0
  153. package/lib/types/ray-entity.js.map +7 -0
  154. package/lib/types/region-entity.cjs +17 -0
  155. package/lib/types/region-entity.cjs.map +7 -0
  156. package/lib/types/region-entity.js +1 -0
  157. package/lib/types/region-entity.js.map +7 -0
  158. package/lib/types/shape-entity.cjs +17 -0
  159. package/lib/types/shape-entity.cjs.map +7 -0
  160. package/lib/types/shape-entity.js +1 -0
  161. package/lib/types/shape-entity.js.map +7 -0
  162. package/lib/types/table-entity.cjs +17 -0
  163. package/lib/types/table-entity.cjs.map +7 -0
  164. package/lib/types/table-entity.js +1 -0
  165. package/lib/types/table-entity.js.map +7 -0
  166. package/lib/types/tables.cjs.map +1 -1
  167. package/lib/types/tolerance-entity.cjs +17 -0
  168. package/lib/types/tolerance-entity.cjs.map +7 -0
  169. package/lib/types/tolerance-entity.js +1 -0
  170. package/lib/types/tolerance-entity.js.map +7 -0
  171. package/lib/types/trace-entity.cjs +17 -0
  172. package/lib/types/trace-entity.cjs.map +7 -0
  173. package/lib/types/trace-entity.js +1 -0
  174. package/lib/types/trace-entity.js.map +7 -0
  175. package/lib/types/underlay-entity.cjs +17 -0
  176. package/lib/types/underlay-entity.cjs.map +7 -0
  177. package/lib/types/underlay-entity.js +1 -0
  178. package/lib/types/underlay-entity.js.map +7 -0
  179. package/lib/types/wipeout-entity.cjs +17 -0
  180. package/lib/types/wipeout-entity.cjs.map +7 -0
  181. package/lib/types/wipeout-entity.js +1 -0
  182. package/lib/types/wipeout-entity.js.map +7 -0
  183. package/lib/types/xline-entity.cjs +17 -0
  184. package/lib/types/xline-entity.cjs.map +7 -0
  185. package/lib/types/xline-entity.js +1 -0
  186. package/lib/types/xline-entity.js.map +7 -0
  187. package/lib/util/escapeXmlText.cjs +27 -0
  188. package/lib/util/escapeXmlText.cjs.map +7 -0
  189. package/lib/util/escapeXmlText.js +7 -0
  190. package/lib/util/escapeXmlText.js.map +7 -0
  191. package/package.json +9 -18
  192. package/playwright.config.cjs +20 -0
  193. package/src/Helper.ts +8 -3
  194. package/src/denormalise.ts +182 -116
  195. package/src/dimensionToSVG.ts +466 -54
  196. package/src/entityToPolyline.ts +124 -2
  197. package/src/handlers/entities.ts +129 -34
  198. package/src/handlers/entity/dgnUnderlay.ts +94 -0
  199. package/src/handlers/entity/dimension.ts +27 -1
  200. package/src/handlers/entity/dwfUnderlay.ts +94 -0
  201. package/src/handlers/entity/image.ts +118 -0
  202. package/src/handlers/entity/leader.ts +153 -0
  203. package/src/handlers/entity/mleader.ts +46 -0
  204. package/src/handlers/entity/mline.ts +74 -0
  205. package/src/handlers/entity/oleframe.ts +62 -0
  206. package/src/handlers/entity/pdfUnderlay.ts +94 -0
  207. package/src/handlers/entity/ray.ts +52 -0
  208. package/src/handlers/entity/region.ts +42 -0
  209. package/src/handlers/entity/shape.ts +73 -0
  210. package/src/handlers/entity/table.ts +49 -0
  211. package/src/handlers/entity/tolerance.ts +75 -0
  212. package/src/handlers/entity/trace.ts +72 -0
  213. package/src/handlers/entity/wipeout.ts +114 -0
  214. package/src/handlers/entity/xline.ts +52 -0
  215. package/src/handlers/objects.ts +379 -139
  216. package/src/handlers/tables.ts +134 -21
  217. package/src/index.ts +9 -18
  218. package/src/toJson.ts +8 -0
  219. package/src/toSVG.ts +143 -10
  220. package/src/types/dimension-entity.ts +11 -0
  221. package/src/types/entity.ts +30 -0
  222. package/src/types/helper.ts +2 -1
  223. package/src/types/image-entity.ts +35 -0
  224. package/src/types/index.ts +14 -0
  225. package/src/types/leader-entity.ts +40 -0
  226. package/src/types/mleader-entity.ts +8 -0
  227. package/src/types/mline-entity.ts +12 -0
  228. package/src/types/oleframe-entity.ts +40 -0
  229. package/src/types/options.ts +48 -0
  230. package/src/types/ray-entity.ts +12 -0
  231. package/src/types/region-entity.ts +11 -0
  232. package/src/types/shape-entity.ts +19 -0
  233. package/src/types/table-entity.ts +14 -0
  234. package/src/types/tables.ts +160 -0
  235. package/src/types/tolerance-entity.ts +20 -0
  236. package/src/types/trace-entity.ts +14 -0
  237. package/src/types/underlay-entity.ts +35 -0
  238. package/src/types/wipeout-entity.ts +20 -0
  239. package/src/types/xline-entity.ts +12 -0
  240. package/src/util/escapeXmlText.ts +10 -0
  241. package/tools/browser_test_server.cjs +87 -0
  242. package/tools/ezdxf_generate_dimensions_all_types.py +246 -0
  243. package/tools/ezdxf_generate_dimensions_angular_3p.py +59 -0
  244. package/tools/ezdxf_generate_dimensions_large_scale.py +87 -0
  245. package/tools/ezdxf_regenerate_problem_fixtures.py +184 -0
  246. package/tools/ezdxf_validate_fixtures.py +165 -0
  247. package/docs/DIMENSION_SUMMARY.md +0 -248
  248. package/docs/DIMENSION_SUMMARY.pt-BR.md +0 -248
  249. package/docs/IMPLEMENTED-2D-ENTITIES.md +0 -54
  250. package/docs/IMPLEMENTED-2D-ENTITIES.pt-BR.md +0 -54
  251. package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.md +0 -241
  252. package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.pt-BR.md +0 -169
package/.eslintrc.json CHANGED
@@ -5,9 +5,7 @@
5
5
  "node": true
6
6
  },
7
7
  "extends": [
8
- "plugin:react/recommended",
9
8
  "standard",
10
- "standard-react",
11
9
  "prettier"
12
10
  ],
13
11
  "globals": {
@@ -21,25 +19,12 @@
21
19
  "afterEach": "readonly"
22
20
  },
23
21
  "parserOptions": {
24
- "babelOptions": {
25
- "presets": ["@babel/preset-react"]
26
- },
27
- "ecmaFeatures": {
28
- "jsx": true
29
- },
30
- "ecmaVersion": 2018,
22
+ "ecmaVersion": 2020,
31
23
  "sourceType": "module"
32
24
  },
33
- "plugins": ["react"],
34
- "parser": "@babel/eslint-parser",
35
25
  "rules": {
36
26
  "no-lone-blocks": "off"
37
27
  },
38
- "settings": {
39
- "react": {
40
- "version": "detect"
41
- }
42
- },
43
28
  "overrides": [
44
29
  {
45
30
  "files": ["*.ts", "*.tsx"],
@@ -22,7 +22,7 @@ This document codifies the current implementation patterns used in DXF-Renewed,
22
22
  Best practices:
23
23
 
24
24
  - Prefer `import type { ... }` for type-only imports.
25
- - Avoid `any` in new code. If runtime constraints require it, keep it local and document why.
25
+ - Avoid `any` or `unknown` in new code. If runtime constraints require it, keep it local and document why.
26
26
  - Keep names and comments in **English (en_US)**.
27
27
 
28
28
  ## Project Architecture (High-Level)
@@ -0,0 +1,161 @@
1
+ ---
2
+ applyTo: '**/*'
3
+ ---
4
+
5
+ # Development Instructions (DXF-Renewed) — using ezdxf
6
+
7
+ This repository is a TypeScript DXF parser. For DXF fixtures, debugging, and cross-checking group codes, we use the Python library **ezdxf**.
8
+
9
+ Official docs:
10
+
11
+ - Setup (extras): <https://ezdxf.readthedocs.io/en/stable/setup.html#installation-with-extras>
12
+ - Reference index: <https://ezdxf.readthedocs.io/en/stable/reference.html>
13
+
14
+ ## 1) Install ezdxf (recommended: local venv)
15
+
16
+ Many Linux distributions use an externally-managed Python environment (PEP 668), which blocks `pip install --user`.
17
+ Use a local virtualenv inside this repo:
18
+
19
+ ```bash
20
+ cd <path-to>/DXF-Renewed
21
+ python3 -m venv .venv-ezdxf
22
+ . .venv-ezdxf/bin/activate
23
+ python -m pip install -U pip
24
+
25
+ # Core library
26
+ python -m pip install -U ezdxf
27
+
28
+ # Optional drawing add-on dependencies (recommended by ezdxf docs)
29
+ python -m pip install -U 'ezdxf[draw]'
30
+ ```
31
+
32
+ Extras from the ezdxf docs:
33
+
34
+ - `ezdxf[draw]`: Matplotlib, PySide6, PyMuPDF, Pillow
35
+ - `ezdxf[dev]`: `draw` + setuptools, wheel, Cython, pytest
36
+ - If PySide6 is not available, use `ezdxf[draw5]` / `ezdxf[dev5]` (PyQt5-based)
37
+
38
+ Verify:
39
+
40
+ ```bash
41
+ . .venv-ezdxf/bin/activate
42
+ python -m ezdxf -V
43
+ ```
44
+
45
+ ## 2) How ezdxf helps this repo
46
+
47
+ Use ezdxf for:
48
+
49
+ - generating **minimal DXF fixtures** for TDD (`test/resources/*.dxf`)
50
+ - dumping **raw group-code tags** for an entity/object/table
51
+ - checking real-world DXF parsing expectations without guessing group codes
52
+
53
+ This repo’s workflow is TDD-first:
54
+
55
+ - add a minimal fixture + failing unit test
56
+ - implement parser support
57
+ - keep `yarn test` + `yarn lint` green
58
+
59
+ ## 3) Inspect an existing DXF fixture
60
+
61
+ Print entity types, handles, and layers:
62
+
63
+ ```bash
64
+ . .venv-ezdxf/bin/activate
65
+ python - <<'PY'
66
+ import ezdxf
67
+
68
+ doc = ezdxf.readfile('test/resources/entities.dxf')
69
+ msp = doc.modelspace()
70
+
71
+ for e in msp:
72
+ handle = getattr(e.dxf, 'handle', None)
73
+ layer = getattr(e.dxf, 'layer', None)
74
+ print(e.dxftype(), handle, layer)
75
+ PY
76
+ ```
77
+
78
+ ## 4) Dump raw group codes (tags) for a single entity
79
+
80
+ This is the most useful thing for implementing a new handler in `src/handlers/entity/*`.
81
+
82
+ ```bash
83
+ . .venv-ezdxf/bin/activate
84
+ python - <<'PY'
85
+ import ezdxf
86
+ from ezdxf.lldxf.tagwriter import TagCollector
87
+
88
+ doc = ezdxf.readfile('test/resources/leader-basic.dxf')
89
+ entity = next(iter(doc.modelspace()))
90
+
91
+ collector = TagCollector()
92
+ entity.export_dxf(collector)
93
+
94
+ for tag in collector.tags:
95
+ print(tag.code, tag.value)
96
+ PY
97
+ ```
98
+
99
+ Tip: If you want to dump all entities:
100
+
101
+ ```bash
102
+ . .venv-ezdxf/bin/activate
103
+ python - <<'PY'
104
+ import ezdxf
105
+ from ezdxf.lldxf.tagwriter import TagCollector
106
+
107
+ doc = ezdxf.readfile('test/resources/entities.dxf')
108
+ for i, entity in enumerate(doc.modelspace()):
109
+ print('---', i, entity.dxftype(), '---')
110
+ collector = TagCollector()
111
+ entity.export_dxf(collector)
112
+ for tag in collector.tags:
113
+ print(tag.code, tag.value)
114
+ PY
115
+ ```
116
+
117
+ ## 5) Generate a new minimal fixture (recommended pattern)
118
+
119
+ If ezdxf supports the entity via `layout.new_entity()`, you can create it directly.
120
+
121
+ Example: create a minimal `TOLERANCE` entity and export:
122
+
123
+ ```bash
124
+ . .venv-ezdxf/bin/activate
125
+ python - <<'PY'
126
+ import ezdxf
127
+
128
+ doc = ezdxf.new('R2010')
129
+ msp = doc.modelspace()
130
+
131
+ # Create entity by DXF type name. dxfattribs depends on entity.
132
+ # "insert" maps to group codes 10/20/30 for many entities.
133
+ fcf = msp.new_entity('TOLERANCE', dxfattribs={
134
+ 'layer': '0',
135
+ 'insert': (10, 20, 0),
136
+ })
137
+
138
+ # You can set additional attributes if supported:
139
+ # fcf.dxf.text = '%%v%%v'
140
+
141
+ out = 'test/resources/tolerance-basic.dxf'
142
+ doc.saveas(out)
143
+ print('wrote', out)
144
+ PY
145
+ ```
146
+
147
+ If the high-level attribute you need is unclear, use the **tag dump** technique above to learn what ezdxf writes.
148
+
149
+ ## 6) Run DXF-Renewed checks
150
+
151
+ ```bash
152
+ cd <path-to>/DXF-Renewed
153
+ yarn test
154
+ yarn lint
155
+ ```
156
+
157
+ ## 7) Reference sitemap
158
+
159
+ Curated ezdxf reference links live here:
160
+
161
+ - docs/EZDXF_REFERENCE_SITEMAP.md
@@ -0,0 +1,271 @@
1
+ ---
2
+ applyTo: '**/*'
3
+ ---
4
+
5
+ # Test-Driven Development (TDD) Principles - AI Instructions
6
+
7
+ ## Core TDD Workflow
8
+
9
+ 1. **RED**: Write failing test first
10
+ 2. **GREEN**: Write minimal code to pass test
11
+ 3. **REFACTOR**: Improve code while maintaining test pass
12
+
13
+ ## Mandatory Rules
14
+
15
+ ### Test-First Discipline
16
+
17
+ - NEVER write production code without failing test
18
+ - Test describes expected behavior before implementation
19
+ - Watch test fail before writing implementation
20
+ - Verify test passes after implementation
21
+
22
+ ### Minimal Implementation
23
+
24
+ - Write ONLY code needed to pass current test
25
+ - Avoid premature optimization
26
+ - Resist implementing features without tests
27
+ - Each test drives one specific behavior
28
+
29
+ ### Test Quality Standards
30
+
31
+ - Tests must be deterministic (same input = same output)
32
+ - Tests should be independent (no execution order dependency)
33
+ - Use descriptive test names explaining expected behavior
34
+ - One assertion concept per test (arrange, act, assert)
35
+
36
+ ## Test Structure Pattern
37
+
38
+ ```typescript
39
+ describe('UnitUnderTest', () => {
40
+ // Arrange: Setup test data and mocks
41
+ const input = validInput();
42
+ const expected = expectedOutput();
43
+
44
+ // Act: Execute function/method
45
+ const result = functionUnderTest(input);
46
+
47
+ // Assert: Verify result matches expectation
48
+ expect(result).toEqual(expected);
49
+ });
50
+ ```
51
+
52
+ ## Code Coverage Requirements
53
+
54
+ - Aim for 100% line coverage
55
+ - 100% branch coverage (all if/else paths)
56
+ - 100% function coverage
57
+ - Use Istanbul/c8 for coverage reporting
58
+ - Uncovered code indicates missing tests
59
+
60
+ ## Anti-Patterns to Avoid
61
+
62
+ ### Do NOT
63
+
64
+ - Write implementation before test
65
+ - Write multiple tests before implementation
66
+ - Skip watching test fail
67
+ - Test implementation details instead of behavior
68
+ - Couple tests to internal structure
69
+ - Use random/non-deterministic test data
70
+ - Share state between tests
71
+
72
+ ### Do NOT Cheat
73
+
74
+ - Hard-coding expected results to pass tests
75
+ - Writing `if` statements matching test inputs
76
+ - Returning specific values for test cases
77
+ - Example of cheating:
78
+ ```typescript
79
+ // BAD: Hard-coded for specific test
80
+ function calculate(a: number, b: number): number {
81
+ if (a === 215 && b === 300) return 85;
82
+ if (a === 486 && b === 600) return 114;
83
+ return 0;
84
+ }
85
+ ```
86
+
87
+ ## Mocking Strategy
88
+
89
+ ### When to Mock
90
+
91
+ - External dependencies (APIs, databases, file system)
92
+ - Time-dependent operations (Date.now(), timers)
93
+ - Random operations (Math.random())
94
+ - Complex dependencies not under test
95
+ - Async operations (Promises, Observables)
96
+
97
+ ### Mock Requirements
98
+
99
+ - Mock external service calls
100
+ - Mock database queries
101
+ - Mock file I/O operations
102
+ - Use spy functions to verify interactions
103
+ - Return predictable, synchronous data when possible
104
+
105
+ ### Mock Example
106
+
107
+ ```typescript
108
+ // Mock Observable service method
109
+ jest.spyOn(service, 'get').mockReturnValue(
110
+ of({
111
+ id: 1,
112
+ data: 'test',
113
+ toJson: () => ({ id: 1, data: 'test' }),
114
+ }),
115
+ );
116
+ ```
117
+
118
+ ## Handling Async Operations
119
+
120
+ ### Observable/Promise Patterns
121
+
122
+ - Use `firstValueFrom()` in implementation
123
+ - Mock Observables with `of()` or `throwError()`
124
+ - Properly handle async/await in tests
125
+ - Ensure all Observables complete in tests
126
+
127
+ ### Timeout Prevention
128
+
129
+ - Mock all external async operations
130
+ - Avoid real HTTP calls in unit tests
131
+ - Mock timers with `jest.useFakeTimers()`
132
+ - Set reasonable test timeouts
133
+
134
+ ## Test Organization
135
+
136
+ ### File Structure
137
+
138
+ - `*.spec.ts` for unit tests (same directory as source)
139
+ - `*.test.ts` for integration tests
140
+ - `*.e2e.ts` for end-to-end tests
141
+ - One test file per source file
142
+
143
+ ### Test Grouping
144
+
145
+ ```typescript
146
+ describe('ServiceName', () => {
147
+ describe('methodName', () => {
148
+ it('should handle valid input', () => {});
149
+ it('should throw on invalid input', () => {});
150
+ it('should return empty for edge case', () => {});
151
+ });
152
+ });
153
+ ```
154
+
155
+ ## Regression Prevention
156
+
157
+ - All tests must pass before commit
158
+ - New features require new tests
159
+ - Bug fixes require reproduction test
160
+ - Refactoring must not break existing tests
161
+ - Use CI to enforce test pass
162
+
163
+ ## Documentation Through Tests
164
+
165
+ - Tests serve as executable documentation
166
+ - Test names explain functionality
167
+ - Use JSDoc comments for complex logic
168
+ - Include usage examples in test descriptions
169
+
170
+ ## Performance Considerations
171
+
172
+ - Unit tests should run fast (< 1s per test)
173
+ - Mock slow operations
174
+ - Use test parallelization
175
+ - Avoid real database/network in unit tests
176
+ - Integration tests can be slower
177
+
178
+ ## Implementation Workflow
179
+
180
+ 1. Write test describing one behavior
181
+ 2. Run test → verify it fails
182
+ 3. Write minimum code to pass test
183
+ 4. Run test → verify it passes
184
+ 5. Refactor if needed
185
+ 6. Run all tests → verify no regression
186
+ 7. Repeat for next behavior
187
+
188
+ ## Red-Green-Refactor Cycle
189
+
190
+ **RED Phase:**
191
+
192
+ - Write test for non-existent functionality
193
+ - Test must fail with meaningful error
194
+ - Verify test failure reason is correct
195
+
196
+ **GREEN Phase:**
197
+
198
+ - Write simplest code to make test pass
199
+ - Don't worry about code quality yet
200
+ - Focus only on making test green
201
+
202
+ **REFACTOR Phase:**
203
+
204
+ - Improve code structure
205
+ - Remove duplication
206
+ - Optimize performance if needed
207
+ - All tests must remain green
208
+
209
+ ## Practical Example: Vending Machine Change
210
+
211
+ **Requirement:** Calculate coin change for vending machine
212
+
213
+ **Test 1 - Empty Case:**
214
+
215
+ ```typescript
216
+ test('getChange(1,1) returns empty array', () => {
217
+ expect(getChange(1, 1)).toEqual([]);
218
+ });
219
+ ```
220
+
221
+ **Implementation 1:**
222
+
223
+ ```typescript
224
+ function getChange(payable: number, paid: number): number[] {
225
+ return [];
226
+ }
227
+ ```
228
+
229
+ **Test 2 - Basic Change:**
230
+
231
+ ```typescript
232
+ test('getChange(215, 300) returns [50,20,10,5]', () => {
233
+ expect(getChange(215, 300)).toEqual([50, 20, 10, 5]);
234
+ });
235
+ ```
236
+
237
+ **Implementation 2:**
238
+
239
+ ```typescript
240
+ function getChange(payable: number, paid: number): number[] {
241
+ const coins = [200, 100, 50, 20, 10, 5, 2, 1];
242
+ const change: number[] = [];
243
+ let remaining = paid - payable;
244
+
245
+ for (const coin of coins) {
246
+ while (remaining >= coin) {
247
+ change.push(coin);
248
+ remaining -= coin;
249
+ }
250
+ }
251
+
252
+ return change;
253
+ }
254
+ ```
255
+
256
+ ## Summary Checklist
257
+
258
+ Before writing any production code:
259
+
260
+ - [ ] Write failing test
261
+ - [ ] Verify test fails with expected reason
262
+ - [ ] Write minimal implementation
263
+ - [ ] Verify test passes
264
+ - [ ] Verify no test regressions
265
+ - [ ] Refactor if needed
266
+ - [ ] All tests still pass
267
+
268
+ ## Reference Sources
269
+
270
+ Based on: https://github.com/dwyl/learn-tdd
271
+ Key principles: Red-Green-Refactor, Test-First, Minimal Implementation
Binary file
@@ -0,0 +1,163 @@
1
+ # Architecture
2
+
3
+ This document describes the high-level architecture of DXF-Renewed, including the parsing pipeline, denormalisation (INSERT expansion), and rendering outputs.
4
+
5
+ ## Goals
6
+
7
+ - Parse DXF text into a typed model deterministically.
8
+ - Expand INSERT/BLOCK references into a flattened entity list with transforms.
9
+ - Provide multiple output formats:
10
+ - SVG string (`toSVG`)
11
+ - numeric polylines (`toPolylines`)
12
+ - JSON string (`toJson`)
13
+ - Prefer "parse what we can, warn for what we can’t" over throwing, when feasible.
14
+
15
+ ## Project Layout
16
+
17
+ - `src/` — TypeScript source
18
+ - `src/index.ts` — public API exports
19
+ - `src/Helper.ts` — convenience wrapper around parsing + denormalisation + outputs
20
+ - `src/parseString.ts` — main DXF text parser (routes sections)
21
+ - `src/handlers/` — section handlers and entity handlers
22
+ - `src/types/` — public type definitions
23
+ - `src/denormalise.ts` — INSERT expansion + transform stacking
24
+ - `src/toSVG.ts` — SVG renderer
25
+ - `src/toPolylines.ts` + `src/entityToPolyline.ts` — polyline renderer
26
+ - `src/toJson.ts` — JSON serializer for the parsed model
27
+ - `src/util/` — shared helpers (logger, XML escaping, etc.)
28
+ - `test/` — tests and fixtures
29
+ - `test/unit/` — unit tests (Mocha + TSX)
30
+ - `test/integration-browser/` — Playwright browser rendering tests
31
+ - `test/resources/` — DXF fixtures
32
+ - `docs/` — documentation and references
33
+ - `lib/` and `dist/` — build outputs
34
+
35
+ ## Data Flow (End-to-End)
36
+
37
+ Typical usage:
38
+
39
+ 1. `parseString(dxfText)` produces a `ParsedDXF` object.
40
+ 2. `denormalise(parsed)` expands block inserts and returns a flattened `Entity[]`.
41
+ 3. Render or export:
42
+ - `toSVG(parsed)` renders the denormalised entities into an SVG string.
43
+ - `toPolylines(parsed)` converts supported entities into numeric polyline arrays.
44
+ - `toJson(parsed)` serializes the `ParsedDXF` model into a JSON string.
45
+
46
+ The `Helper` class wraps this pipeline:
47
+
48
+ - Constructs from DXF text
49
+ - Exposes `parsed` and `denormalised`
50
+ - Exposes `toSVG()`, `toPolylines()`, and `toJson()`
51
+
52
+ ### Pipeline Diagram
53
+
54
+ ```mermaid
55
+ flowchart LR
56
+ A[DXF text] --> B[parseString]
57
+ B --> C[ParsedDXF]
58
+
59
+ subgraph SectionHandlers[Section handlers]
60
+ H[HEADER]
61
+ T[TABLES]
62
+ BL[BLOCKS]
63
+ E[ENTITIES]
64
+ O[OBJECTS]
65
+ end
66
+
67
+ B -. routes sections .-> SectionHandlers
68
+ SectionHandlers -. populate .-> C
69
+
70
+ C --> D[denormalise]
71
+ D --> E2["Entity[] (flattened + transforms)"]
72
+
73
+ E2 --> S[toSVG]
74
+ E2 --> P[toPolylines]
75
+ C --> J[toJson]
76
+
77
+ S --> S2[SVG string]
78
+ P --> P2[Polyline arrays]
79
+ J --> J2[JSON string]
80
+
81
+ A --> HLP[Helper]
82
+ HLP --> C
83
+ HLP --> E2
84
+ HLP --> S2
85
+ HLP --> P2
86
+ HLP --> J2
87
+ ```
88
+
89
+ ## Parsing
90
+
91
+ ### Tuple Stream
92
+
93
+ The parser converts the DXF text into a tuple stream of `[groupCode, value]` and routes it by section.
94
+
95
+ ### Section Routing
96
+
97
+ `src/parseString.ts` is responsible for splitting tuples into sections and delegating to section handlers:
98
+
99
+ - `src/handlers/header.ts`
100
+ - `src/handlers/tables.ts`
101
+ - `src/handlers/blocks.ts`
102
+ - `src/handlers/entities.ts`
103
+ - `src/handlers/objects.ts`
104
+
105
+ ### Entity Handlers
106
+
107
+ Entity handlers live in `src/handlers/entity/*.ts` and follow a consistent pattern:
108
+
109
+ - Export `TYPE` (DXF entity type string).
110
+ - Export a `process(tuples)` function that reduces group codes into a typed entity.
111
+ - Delegate common fields (layer, color, handle, etc.) to shared parsing helpers.
112
+
113
+ Multi-entity sequences (e.g. `POLYLINE` → `VERTEX`… → `SEQEND`) are handled by sequencing logic in `src/handlers/entities.ts`.
114
+
115
+ ## Denormalisation (INSERT Expansion)
116
+
117
+ `src/denormalise.ts` expands `INSERT` entities into the referenced BLOCK contents.
118
+
119
+ Responsibilities:
120
+
121
+ - Resolve INSERT → BLOCK.
122
+ - Apply transform stacks to expanded entities.
123
+ - Expand rectangular arrays when present.
124
+
125
+ The output is a flat list of entities with an optional `transforms` stack used by renderers.
126
+
127
+ ## Rendering
128
+
129
+ ### SVG (`toSVG`)
130
+
131
+ `src/toSVG.ts` renders the denormalised entities.
132
+
133
+ - Uses native SVG primitives when feasible (`<circle>`, `<ellipse>`, path arcs).
134
+ - Uses polyline approximations for entities that do not have a native SVG primitive or where approximation is acceptable.
135
+ - Unsupported entity types are skipped with a warning.
136
+
137
+ ### Polylines (`toPolylines`)
138
+
139
+ `src/entityToPolyline.ts` is the main conversion point for entities → polylines.
140
+
141
+ - Designed to be pure: same input entity should result in the same polyline output.
142
+ - Options (e.g., interpolation density) should be expressed via `ToPolylinesOptions`.
143
+
144
+ ### JSON (`toJson`)
145
+
146
+ `src/toJson.ts` provides a stable way to serialize the parsed model.
147
+
148
+ - Intended to represent the parsed model 1-to-1.
149
+ - Supports pretty-printing via options.
150
+
151
+ ## Logging & Error Handling
152
+
153
+ - Logging goes through `src/util/logger.ts`.
154
+ - Prefer warnings over exceptions for unsupported features.
155
+ - Parsing should remain resilient: bad/unknown codes should not crash the entire parse when possible.
156
+
157
+ ## Build & Test
158
+
159
+ - Build: TypeScript + esbuild bundling.
160
+ - Unit tests: Mocha executed with `tsx`.
161
+ - Browser integration tests: Playwright (renders fixtures and captures screenshots under `test/rendered/`).
162
+ - Functional manual viewer: Vite dev server under `test/functional/`.
163
+
package/CHANGELOG.md CHANGED
@@ -5,6 +5,45 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## 7.2.0 (2026-01-01)
9
+
10
+ * Merge pull request #2 from linkiez/feature/2026.01.01 ([c01512f](https://github.com/linkiez/DXF-Renewed/commit/c01512f)), closes [#2](https://github.com/linkiez/DXF-Renewed/issues/2)
11
+ * docs: add architecture diagram ([7f61ef2](https://github.com/linkiez/DXF-Renewed/commit/7f61ef2))
12
+ * docs: clarify supported entities ([8cd47dc](https://github.com/linkiez/DXF-Renewed/commit/8cd47dc))
13
+ * docs: consolidate documentation into PLAN.md ([204abf9](https://github.com/linkiez/DXF-Renewed/commit/204abf9))
14
+ * docs: fix mermaid diagram parsing ([0cedf8d](https://github.com/linkiez/DXF-Renewed/commit/0cedf8d))
15
+ * docs: improve README structure ([3c6659d](https://github.com/linkiez/DXF-Renewed/commit/3c6659d))
16
+ * docs: rename plan to roadmap ([23b060e](https://github.com/linkiez/DXF-Renewed/commit/23b060e))
17
+ * docs: update README progress ([64566b7](https://github.com/linkiez/DXF-Renewed/commit/64566b7))
18
+ * feat: add toJson processor ([94e112c](https://github.com/linkiez/DXF-Renewed/commit/94e112c))
19
+ * feat(entities): add handlers for additional 2D entities ([221ef8b](https://github.com/linkiez/DXF-Renewed/commit/221ef8b))
20
+ * feat(parser): add FIELD/DIMASSOC objects and extra table types ([ef89ed7](https://github.com/linkiez/DXF-Renewed/commit/ef89ed7))
21
+ * feat(render): support LEADER/RAY/XLINE/TRACE/SHAPE/WIPEOUT ([05a7c82](https://github.com/linkiez/DXF-Renewed/commit/05a7c82))
22
+ * chore(tooling): remove babel/react/webpack and migrate functional tests to vite ([dd92031](https://github.com/linkiez/DXF-Renewed/commit/dd92031))
23
+
24
+ ## 7.1.0 (2026-01-01)
25
+
26
+ * Merge pull request #1 from linkiez/feat/seqend-sequencing ([068c6e1](https://github.com/linkiez/DXF-Renewed/commit/068c6e1)), closes [#1](https://github.com/linkiez/DXF-Renewed/issues/1)
27
+ * docs: add ezdxf reference sitemap and dev instructions ([859da63](https://github.com/linkiez/DXF-Renewed/commit/859da63))
28
+ * docs: add SVG rendering integration testing docs ([5bb0dbb](https://github.com/linkiez/DXF-Renewed/commit/5bb0dbb))
29
+ * docs: clarify type safety guidance ([dc01286](https://github.com/linkiez/DXF-Renewed/commit/dc01286))
30
+ * docs: consolidate documentation and plan ([2f4f01e](https://github.com/linkiez/DXF-Renewed/commit/2f4f01e))
31
+ * docs: switch to main-only workflow ([6098ad6](https://github.com/linkiez/DXF-Renewed/commit/6098ad6))
32
+ * docs: update dimension docs and test guidance ([c171703](https://github.com/linkiez/DXF-Renewed/commit/c171703))
33
+ * chore: ignore local ezdxf venv ([053e4c4](https://github.com/linkiez/DXF-Renewed/commit/053e4c4))
34
+ * chore(fixtures): add ezdxf validation tooling ([c81c871](https://github.com/linkiez/DXF-Renewed/commit/c81c871))
35
+ * chore(fixtures): regenerate DXF fixtures via ezdxf ([7c6876d](https://github.com/linkiez/DXF-Renewed/commit/7c6876d))
36
+ * chore(tests): track rendered screenshots ([ebcd1f1](https://github.com/linkiez/DXF-Renewed/commit/ebcd1f1))
37
+ * test(dimension): add fixtures for all dimension types ([6b5f9cf](https://github.com/linkiez/DXF-Renewed/commit/6b5f9cf))
38
+ * test(integration): add node DIMENSION SVG rendering test ([820efc6](https://github.com/linkiez/DXF-Renewed/commit/820efc6))
39
+ * test(integration): run SVG rendering tests in browser ([b0abe31](https://github.com/linkiez/DXF-Renewed/commit/b0abe31))
40
+ * feat(dimension): add angular 3-point rendering ([a9ee537](https://github.com/linkiez/DXF-Renewed/commit/a9ee537))
41
+ * feat(entities): add image, underlay, leader, and tolerance support ([7f17e47](https://github.com/linkiez/DXF-Renewed/commit/7f17e47))
42
+ * feat(objects): add handle maps for common DXF objects ([7672211](https://github.com/linkiez/DXF-Renewed/commit/7672211))
43
+ * style: normalize import ordering ([55d54c1](https://github.com/linkiez/DXF-Renewed/commit/55d54c1))
44
+ * fix(denormalise): apply block basepoint to TEXT/MTEXT/DIMENSION ([1ee560e](https://github.com/linkiez/DXF-Renewed/commit/1ee560e))
45
+ * fix(parser): harden POLYLINE sequencing ([7eb1fb7](https://github.com/linkiez/DXF-Renewed/commit/7eb1fb7))
46
+
8
47
  ## 7.0.0 (2025-12-31)
9
48
 
10
49
  * fix: consolidar tipos ParsedDXF e corrigir incompatibilidades ([804c485](https://github.com/linkiez/DXF-Renewed/commit/804c485))