@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.
- package/.eslintrc.json +1 -16
- package/.github/instructions/code-patterns.instructions.md +1 -1
- package/.github/instructions/exdxf.instruction.md +161 -0
- package/.github/instructions/tdd.instructions.md +271 -0
- package/.yarn/install-state.gz +0 -0
- package/ARCHITECTURE.md +163 -0
- package/CHANGELOG.md +39 -0
- package/CONTRIBUTING.md +16 -14
- package/README.md +113 -16
- package/{PLAN.md → ROADMAP.md} +244 -102
- package/dist/dxf.js +2212 -454
- package/docs/EZDXF_REFERENCE_SITEMAP.md +55 -0
- package/docs/FIXTURE_VALIDATION_EZDXF.md +62 -0
- package/lib/Helper.cjs +6 -2
- package/lib/Helper.cjs.map +3 -3
- package/lib/Helper.js +6 -2
- package/lib/Helper.js.map +2 -2
- package/lib/denormalise.cjs +131 -91
- package/lib/denormalise.cjs.map +2 -2
- package/lib/denormalise.js +131 -91
- package/lib/denormalise.js.map +2 -2
- package/lib/dimensionToSVG.cjs +318 -53
- package/lib/dimensionToSVG.cjs.map +3 -3
- package/lib/dimensionToSVG.js +316 -52
- package/lib/dimensionToSVG.js.map +2 -2
- package/lib/entityToPolyline.cjs +95 -0
- package/lib/entityToPolyline.cjs.map +3 -3
- package/lib/entityToPolyline.js +95 -0
- package/lib/entityToPolyline.js.map +2 -2
- package/lib/handlers/entities.cjs +111 -27
- package/lib/handlers/entities.cjs.map +3 -3
- package/lib/handlers/entities.js +111 -27
- package/lib/handlers/entities.js.map +3 -3
- package/lib/handlers/entity/dgnUnderlay.cjs +106 -0
- package/lib/handlers/entity/dgnUnderlay.cjs.map +7 -0
- package/lib/handlers/entity/dgnUnderlay.js +71 -0
- package/lib/handlers/entity/dgnUnderlay.js.map +7 -0
- package/lib/handlers/entity/dimension.cjs +24 -0
- package/lib/handlers/entity/dimension.cjs.map +2 -2
- package/lib/handlers/entity/dimension.js +24 -0
- package/lib/handlers/entity/dimension.js.map +2 -2
- package/lib/handlers/entity/dwfUnderlay.cjs +106 -0
- package/lib/handlers/entity/dwfUnderlay.cjs.map +7 -0
- package/lib/handlers/entity/dwfUnderlay.js +71 -0
- package/lib/handlers/entity/dwfUnderlay.js.map +7 -0
- package/lib/handlers/entity/image.cjs +123 -0
- package/lib/handlers/entity/image.cjs.map +7 -0
- package/lib/handlers/entity/image.js +88 -0
- package/lib/handlers/entity/image.js.map +7 -0
- package/lib/handlers/entity/leader.cjs +148 -0
- package/lib/handlers/entity/leader.cjs.map +7 -0
- package/lib/handlers/entity/leader.js +113 -0
- package/lib/handlers/entity/leader.js.map +7 -0
- package/lib/handlers/entity/mleader.cjs +69 -0
- package/lib/handlers/entity/mleader.cjs.map +7 -0
- package/lib/handlers/entity/mleader.js +34 -0
- package/lib/handlers/entity/mleader.js.map +7 -0
- package/lib/handlers/entity/mline.cjs +91 -0
- package/lib/handlers/entity/mline.cjs.map +7 -0
- package/lib/handlers/entity/mline.js +56 -0
- package/lib/handlers/entity/mline.js.map +7 -0
- package/lib/handlers/entity/oleframe.cjs +98 -0
- package/lib/handlers/entity/oleframe.cjs.map +7 -0
- package/lib/handlers/entity/oleframe.js +63 -0
- package/lib/handlers/entity/oleframe.js.map +7 -0
- package/lib/handlers/entity/pdfUnderlay.cjs +106 -0
- package/lib/handlers/entity/pdfUnderlay.cjs.map +7 -0
- package/lib/handlers/entity/pdfUnderlay.js +71 -0
- package/lib/handlers/entity/pdfUnderlay.js.map +7 -0
- package/lib/handlers/entity/ray.cjs +81 -0
- package/lib/handlers/entity/ray.cjs.map +7 -0
- package/lib/handlers/entity/ray.js +46 -0
- package/lib/handlers/entity/ray.js.map +7 -0
- package/lib/handlers/entity/region.cjs +67 -0
- package/lib/handlers/entity/region.cjs.map +7 -0
- package/lib/handlers/entity/region.js +32 -0
- package/lib/handlers/entity/region.js.map +7 -0
- package/lib/handlers/entity/shape.cjs +95 -0
- package/lib/handlers/entity/shape.cjs.map +7 -0
- package/lib/handlers/entity/shape.js +60 -0
- package/lib/handlers/entity/shape.js.map +7 -0
- package/lib/handlers/entity/table.cjs +71 -0
- package/lib/handlers/entity/table.cjs.map +7 -0
- package/lib/handlers/entity/table.js +36 -0
- package/lib/handlers/entity/table.js.map +7 -0
- package/lib/handlers/entity/tolerance.cjs +90 -0
- package/lib/handlers/entity/tolerance.cjs.map +7 -0
- package/lib/handlers/entity/tolerance.js +55 -0
- package/lib/handlers/entity/tolerance.js.map +7 -0
- package/lib/handlers/entity/trace.cjs +101 -0
- package/lib/handlers/entity/trace.cjs.map +7 -0
- package/lib/handlers/entity/trace.js +66 -0
- package/lib/handlers/entity/trace.js.map +7 -0
- package/lib/handlers/entity/wipeout.cjs +122 -0
- package/lib/handlers/entity/wipeout.cjs.map +7 -0
- package/lib/handlers/entity/wipeout.js +87 -0
- package/lib/handlers/entity/wipeout.js.map +7 -0
- package/lib/handlers/entity/xline.cjs +81 -0
- package/lib/handlers/entity/xline.cjs.map +7 -0
- package/lib/handlers/entity/xline.js +46 -0
- package/lib/handlers/entity/xline.js.map +7 -0
- package/lib/handlers/objects.cjs +299 -136
- package/lib/handlers/objects.cjs.map +2 -2
- package/lib/handlers/objects.js +299 -136
- package/lib/handlers/objects.js.map +2 -2
- package/lib/handlers/tables.cjs +96 -17
- package/lib/handlers/tables.cjs.map +2 -2
- package/lib/handlers/tables.js +96 -17
- package/lib/handlers/tables.js.map +2 -2
- package/lib/index.cjs +5 -2
- package/lib/index.cjs.map +3 -3
- package/lib/index.js +18 -16
- package/lib/index.js.map +3 -3
- package/lib/toJson.cjs +29 -0
- package/lib/toJson.cjs.map +7 -0
- package/lib/toJson.js +9 -0
- package/lib/toJson.js.map +7 -0
- package/lib/toSVG.cjs +105 -11
- package/lib/toSVG.cjs.map +3 -3
- package/lib/toSVG.js +106 -12
- package/lib/toSVG.js.map +2 -2
- package/lib/types/dimension-entity.cjs.map +1 -1
- package/lib/types/entity.cjs.map +1 -1
- package/lib/types/helper.cjs.map +1 -1
- package/lib/types/image-entity.cjs +17 -0
- package/lib/types/image-entity.cjs.map +7 -0
- package/lib/types/image-entity.js +1 -0
- package/lib/types/image-entity.js.map +7 -0
- package/lib/types/index.cjs +28 -0
- package/lib/types/index.cjs.map +2 -2
- package/lib/types/index.js +14 -0
- package/lib/types/index.js.map +2 -2
- package/lib/types/leader-entity.cjs +17 -0
- package/lib/types/leader-entity.cjs.map +7 -0
- package/lib/types/leader-entity.js +1 -0
- package/lib/types/leader-entity.js.map +7 -0
- package/lib/types/mleader-entity.cjs +17 -0
- package/lib/types/mleader-entity.cjs.map +7 -0
- package/lib/types/mleader-entity.js +1 -0
- package/lib/types/mleader-entity.js.map +7 -0
- package/lib/types/mline-entity.cjs +17 -0
- package/lib/types/mline-entity.cjs.map +7 -0
- package/lib/types/mline-entity.js +1 -0
- package/lib/types/mline-entity.js.map +7 -0
- package/lib/types/oleframe-entity.cjs +17 -0
- package/lib/types/oleframe-entity.cjs.map +7 -0
- package/lib/types/oleframe-entity.js +1 -0
- package/lib/types/oleframe-entity.js.map +7 -0
- package/lib/types/options.cjs.map +1 -1
- package/lib/types/ray-entity.cjs +17 -0
- package/lib/types/ray-entity.cjs.map +7 -0
- package/lib/types/ray-entity.js +1 -0
- package/lib/types/ray-entity.js.map +7 -0
- package/lib/types/region-entity.cjs +17 -0
- package/lib/types/region-entity.cjs.map +7 -0
- package/lib/types/region-entity.js +1 -0
- package/lib/types/region-entity.js.map +7 -0
- package/lib/types/shape-entity.cjs +17 -0
- package/lib/types/shape-entity.cjs.map +7 -0
- package/lib/types/shape-entity.js +1 -0
- package/lib/types/shape-entity.js.map +7 -0
- package/lib/types/table-entity.cjs +17 -0
- package/lib/types/table-entity.cjs.map +7 -0
- package/lib/types/table-entity.js +1 -0
- package/lib/types/table-entity.js.map +7 -0
- package/lib/types/tables.cjs.map +1 -1
- package/lib/types/tolerance-entity.cjs +17 -0
- package/lib/types/tolerance-entity.cjs.map +7 -0
- package/lib/types/tolerance-entity.js +1 -0
- package/lib/types/tolerance-entity.js.map +7 -0
- package/lib/types/trace-entity.cjs +17 -0
- package/lib/types/trace-entity.cjs.map +7 -0
- package/lib/types/trace-entity.js +1 -0
- package/lib/types/trace-entity.js.map +7 -0
- package/lib/types/underlay-entity.cjs +17 -0
- package/lib/types/underlay-entity.cjs.map +7 -0
- package/lib/types/underlay-entity.js +1 -0
- package/lib/types/underlay-entity.js.map +7 -0
- package/lib/types/wipeout-entity.cjs +17 -0
- package/lib/types/wipeout-entity.cjs.map +7 -0
- package/lib/types/wipeout-entity.js +1 -0
- package/lib/types/wipeout-entity.js.map +7 -0
- package/lib/types/xline-entity.cjs +17 -0
- package/lib/types/xline-entity.cjs.map +7 -0
- package/lib/types/xline-entity.js +1 -0
- package/lib/types/xline-entity.js.map +7 -0
- package/lib/util/escapeXmlText.cjs +27 -0
- package/lib/util/escapeXmlText.cjs.map +7 -0
- package/lib/util/escapeXmlText.js +7 -0
- package/lib/util/escapeXmlText.js.map +7 -0
- package/package.json +9 -18
- package/playwright.config.cjs +20 -0
- package/src/Helper.ts +8 -3
- package/src/denormalise.ts +182 -116
- package/src/dimensionToSVG.ts +466 -54
- package/src/entityToPolyline.ts +124 -2
- package/src/handlers/entities.ts +129 -34
- package/src/handlers/entity/dgnUnderlay.ts +94 -0
- package/src/handlers/entity/dimension.ts +27 -1
- package/src/handlers/entity/dwfUnderlay.ts +94 -0
- package/src/handlers/entity/image.ts +118 -0
- package/src/handlers/entity/leader.ts +153 -0
- package/src/handlers/entity/mleader.ts +46 -0
- package/src/handlers/entity/mline.ts +74 -0
- package/src/handlers/entity/oleframe.ts +62 -0
- package/src/handlers/entity/pdfUnderlay.ts +94 -0
- package/src/handlers/entity/ray.ts +52 -0
- package/src/handlers/entity/region.ts +42 -0
- package/src/handlers/entity/shape.ts +73 -0
- package/src/handlers/entity/table.ts +49 -0
- package/src/handlers/entity/tolerance.ts +75 -0
- package/src/handlers/entity/trace.ts +72 -0
- package/src/handlers/entity/wipeout.ts +114 -0
- package/src/handlers/entity/xline.ts +52 -0
- package/src/handlers/objects.ts +379 -139
- package/src/handlers/tables.ts +134 -21
- package/src/index.ts +9 -18
- package/src/toJson.ts +8 -0
- package/src/toSVG.ts +143 -10
- package/src/types/dimension-entity.ts +11 -0
- package/src/types/entity.ts +30 -0
- package/src/types/helper.ts +2 -1
- package/src/types/image-entity.ts +35 -0
- package/src/types/index.ts +14 -0
- package/src/types/leader-entity.ts +40 -0
- package/src/types/mleader-entity.ts +8 -0
- package/src/types/mline-entity.ts +12 -0
- package/src/types/oleframe-entity.ts +40 -0
- package/src/types/options.ts +48 -0
- package/src/types/ray-entity.ts +12 -0
- package/src/types/region-entity.ts +11 -0
- package/src/types/shape-entity.ts +19 -0
- package/src/types/table-entity.ts +14 -0
- package/src/types/tables.ts +160 -0
- package/src/types/tolerance-entity.ts +20 -0
- package/src/types/trace-entity.ts +14 -0
- package/src/types/underlay-entity.ts +35 -0
- package/src/types/wipeout-entity.ts +20 -0
- package/src/types/xline-entity.ts +12 -0
- package/src/util/escapeXmlText.ts +10 -0
- package/tools/browser_test_server.cjs +87 -0
- package/tools/ezdxf_generate_dimensions_all_types.py +246 -0
- package/tools/ezdxf_generate_dimensions_angular_3p.py +59 -0
- package/tools/ezdxf_generate_dimensions_large_scale.py +87 -0
- package/tools/ezdxf_regenerate_problem_fixtures.py +184 -0
- package/tools/ezdxf_validate_fixtures.py +165 -0
- package/docs/DIMENSION_SUMMARY.md +0 -248
- package/docs/DIMENSION_SUMMARY.pt-BR.md +0 -248
- package/docs/IMPLEMENTED-2D-ENTITIES.md +0 -54
- package/docs/IMPLEMENTED-2D-ENTITIES.pt-BR.md +0 -54
- package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.md +0 -241
- package/docs/TEXT-MTEXT-DIMENSION-SUPPORT.pt-BR.md +0 -169
package/{PLAN.md → ROADMAP.md}
RENAMED
|
@@ -9,6 +9,7 @@ This document describes a phased plan to align this project’s DXF parsing beha
|
|
|
9
9
|
- Provide complete 2D coverage for geometry + annotation features typically found in 2D drawings.
|
|
10
10
|
- Keep backwards compatibility with existing API outputs (`parseString`, `toSVG`, `toPolylines`) where feasible.
|
|
11
11
|
- Grow test coverage using real DXF fixtures and regression tests.
|
|
12
|
+
- Run final SVG rendering integration tests in a real browser and save PNG artifacts for manual review.
|
|
12
13
|
|
|
13
14
|
## Non-goals
|
|
14
15
|
|
|
@@ -16,88 +17,222 @@ This document describes a phased plan to align this project’s DXF parsing beha
|
|
|
16
17
|
- Full ObjectARX/.NET API parity (this is a DXF parser, not a CAD kernel).
|
|
17
18
|
- Perfect fidelity for every proprietary/extension object (fallback behavior is acceptable).
|
|
18
19
|
|
|
19
|
-
##
|
|
20
|
+
## Progress
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
Last updated: 2026-01-01
|
|
23
|
+
|
|
24
|
+
- M0 — Baseline & Regression Harness: done (existing unit + integration coverage is in place).
|
|
25
|
+
- M1 — DXF Format & Section-Level Compliance: ongoing (incremental hardening as fixtures demand).
|
|
26
|
+
- M2 — TABLES Coverage (2D-Relevant): in progress (added minimal parsing for APPID, BLOCK_RECORD, UCS, VIEW).
|
|
27
|
+
- M3 — OBJECTS Coverage (2D-Relevant): in progress (DICTIONARY/XRECORD/IMAGEDEF/UNDERLAY definitions exist; added minimal DIMASSOC parsing).
|
|
28
|
+
- M4 — ENTITIES: Complete 2D Set: ongoing (added TRACE parse + toPolylines support).
|
|
29
|
+
- M5 — Rendering Parity (toPolylines / toSVG): ongoing (TRACE now renders in SVG as a filled path; LEADER now converts to polylines; RAY/XLINE now render via finite polyline fallback; SHAPE renders as text fallback).
|
|
30
|
+
|
|
31
|
+
## References
|
|
32
|
+
|
|
33
|
+
### Primary (ezdxf stable docs)
|
|
34
|
+
|
|
35
|
+
Primary reference used for day-to-day implementation details (entities/objects/tables and their attributes):
|
|
36
|
+
|
|
37
|
+
- ezdxf Reference: <https://ezdxf.readthedocs.io/en/stable/reference.html>
|
|
38
|
+
- Curated sitemap for this repo: [docs/EZDXF_REFERENCE_SITEMAP.md](docs/EZDXF_REFERENCE_SITEMAP.md)
|
|
39
|
+
- Setup / extras install: <https://ezdxf.readthedocs.io/en/stable/setup.html#installation-with-extras>
|
|
40
|
+
|
|
41
|
+
### Authoritative (Autodesk / ObjectARX)
|
|
42
|
+
|
|
43
|
+
When behavior is ambiguous or disputed, treat Autodesk’s DXF reference as authoritative:
|
|
22
44
|
|
|
23
45
|
- Root: <https://help.autodesk.com/view/OARX/2024/ENU/>
|
|
24
46
|
- DXF Format entry point (guid): <https://help.autodesk.com/view/OARX/2024/ENU/?guid=GUID-235B22E0-A567-4CF6-92D3-38A2306D73F3>
|
|
25
47
|
|
|
26
|
-
|
|
48
|
+
Project documentation index:
|
|
49
|
+
|
|
50
|
+
This plan also serves as the documentation index.
|
|
51
|
+
|
|
52
|
+
Standalone reference docs that remain under `docs/`:
|
|
53
|
+
|
|
54
|
+
- `docs/autocad_2012_pdf_dxf-reference_enu.md` (local reference copy)
|
|
55
|
+
- `docs/EZDXF_REFERENCE_SITEMAP.md` (ezdxf reference navigation)
|
|
56
|
+
- `docs/FIXTURE_VALIDATION_EZDXF.md` (ezdxf-based fixture validation)
|
|
57
|
+
|
|
58
|
+
## Documentation (Consolidated)
|
|
59
|
+
|
|
60
|
+
This section consolidates documentation previously living under `docs/` so the project roadmap and implementation guidance are in one place.
|
|
61
|
+
|
|
62
|
+
### Where to Start
|
|
63
|
+
|
|
64
|
+
- Entity support overview: “Implemented Entities (2D)” below
|
|
65
|
+
- DXF version support notes: “DXF Version Support” below
|
|
66
|
+
- Text + annotation notes: “TEXT / MTEXT / DIMENSION (SVG)” below
|
|
67
|
+
- SVG integration testing: “SVG Rendering Integration Tests” below
|
|
68
|
+
- Entity-by-entity workflow: “Entity SVG Roadmap” below
|
|
69
|
+
|
|
70
|
+
### DXF Version Support
|
|
71
|
+
|
|
72
|
+
The parser is designed around DXF group codes and sections, and does not currently gate behavior on `$ACADVER`.
|
|
73
|
+
|
|
74
|
+
In practice, this means:
|
|
75
|
+
|
|
76
|
+
- We aim to parse and render supported entities across many DXF versions.
|
|
77
|
+
- We treat `$ACADVER` primarily as a fixture metadata signal and future compatibility hook.
|
|
78
|
+
|
|
79
|
+
Supporting “the latest AutoCAD DXF” is best defined as:
|
|
80
|
+
|
|
81
|
+
- The library can load DXF files produced by recent AutoCAD versions without rejecting due to version, and
|
|
82
|
+
- The library has fixtures that include a recent `$ACADVER` value, validated by ezdxf.
|
|
83
|
+
|
|
84
|
+
Recommended strategy:
|
|
85
|
+
|
|
86
|
+
- Track `$ACADVER` in fixture validation (see `docs/FIXTURE_VALIDATION_EZDXF.md`).
|
|
87
|
+
- Add at least one fixture exported from a recent AutoCAD version (keep it small and single-purpose; prefer a fixture that includes DIMENSION + text).
|
|
88
|
+
- Add an integration test for that fixture (goal: “does not throw + expected key SVG features exist”).
|
|
89
|
+
- Document which `$ACADVER` values are present in fixtures.
|
|
90
|
+
|
|
91
|
+
Non-goals:
|
|
92
|
+
|
|
93
|
+
- Guarantee support for every new entity introduced by new DXF versions.
|
|
94
|
+
- Guarantee binary DXF support (unless explicitly added).
|
|
95
|
+
|
|
96
|
+
If version-specific behavior is needed later:
|
|
97
|
+
|
|
98
|
+
- Add a header helper that exposes `$ACADVER` in a typed way.
|
|
99
|
+
- Add tests covering version-specific parsing/rendering differences.
|
|
27
100
|
|
|
28
|
-
|
|
101
|
+
### Implemented Entities (2D)
|
|
29
102
|
|
|
30
|
-
|
|
103
|
+
This list was generated based on the AutoCAD 2012 DXF reference documentation. It catalogs 2D entities, indicating whether they have already been implemented in this project.
|
|
31
104
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
105
|
+
| Entity | Implemented | Description |
|
|
106
|
+
| :--- | :---: | :--- |
|
|
107
|
+
| **ARC** | ✅ | A circular arc. |
|
|
108
|
+
| **CIRCLE** | ✅ | A circle. |
|
|
109
|
+
| **ELLIPSE** | ✅ | An ellipse or elliptical arc. |
|
|
110
|
+
| **HATCH** | ✅ | Fills a bounded area with a pattern, solid color, or gradient. |
|
|
111
|
+
| **LINE** | ✅ | A straight line segment. |
|
|
112
|
+
| **LWPOLYLINE** | ✅ | A lightweight 2D polyline. |
|
|
113
|
+
| **MTEXT** | ✅ | Multi-line text with advanced formatting (partial formatting support in SVG). |
|
|
114
|
+
| **POINT** | ✅ | A point entity. |
|
|
115
|
+
| **POLYLINE** | ✅ | A 2D or 3D polyline (with vertices). |
|
|
116
|
+
| **SOLID** | ✅ | A 2D area filled with solid color. |
|
|
117
|
+
| **SPLINE** | ✅ | A spline curve. |
|
|
118
|
+
| **TEXT** | ✅ | A single line of text. |
|
|
119
|
+
| **DIMENSION** | ✅ | Dimension entity (linear, angular, radial, etc.). DIMSTYLE integration and SVG rendering are implemented (see “DIMENSION Implementation Summary”). |
|
|
120
|
+
| **INSERT** | ✅ | A block insertion (block reference). |
|
|
121
|
+
| **ATTDEF** | ✅ | Attribute definition for a block. |
|
|
122
|
+
| **ATTRIB** | ✅ | An attribute instance attached to a block. |
|
|
123
|
+
| **OLE2FRAME** | ✅ | An OLE (Object Linking and Embedding) object. |
|
|
124
|
+
| **LEADER** | ✅ | A leader line, used for annotations. |
|
|
125
|
+
| **MLINE** | ❌ | A multi-line entity with parallel lines. |
|
|
126
|
+
| **RAY** | ✅ | A semi-infinite line that extends infinitely in one direction from its start point. |
|
|
127
|
+
| **SHAPE** | ✅ | A shape from a shape file (.shx). |
|
|
128
|
+
| **TOLERANCE** | ✅ | A geometric tolerance (feature control frame). |
|
|
129
|
+
| **TRACE** | ✅ | A solid 2D line with width. |
|
|
130
|
+
| **WIPEOUT** | ✅ | A background masking area (currently rendered as an outline-only fallback; no masking yet). |
|
|
131
|
+
| **XLINE** | ✅ | An infinite construction line. |
|
|
37
132
|
|
|
38
|
-
###
|
|
133
|
+
### TEXT / MTEXT / DIMENSION (SVG)
|
|
39
134
|
|
|
40
|
-
|
|
41
|
-
- HEADER Section Group Codes (DXF)
|
|
135
|
+
This project supports SVG rendering for TEXT, MTEXT, and DIMENSION entities.
|
|
42
136
|
|
|
43
|
-
|
|
137
|
+
Notes:
|
|
44
138
|
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
139
|
+
- Text font selection is not currently respected in SVG (defaults to browser font).
|
|
140
|
+
- Complex MTEXT formatting is not fully supported (kept intentionally incremental).
|
|
141
|
+
- Text bounding boxes are approximate.
|
|
48
142
|
|
|
49
|
-
|
|
143
|
+
Supported group code highlights:
|
|
50
144
|
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
- APPID (DXF)
|
|
55
|
-
- BLOCK_RECORD (DXF)
|
|
56
|
-
- DIMSTYLE (DXF)
|
|
57
|
-
- LAYER (DXF)
|
|
58
|
-
- LTYPE (DXF)
|
|
59
|
-
- STYLE (DXF)
|
|
60
|
-
- UCS (DXF)
|
|
61
|
-
- VIEW (DXF)
|
|
62
|
-
- VPORT (DXF)
|
|
145
|
+
- TEXT: text (1), insertion point (10/20/30), alignment point (11/21/31), height (40), scale X (41), rotation (50), oblique (51), align (72/73)
|
|
146
|
+
- MTEXT: text (1/3), insertion point (10/20/30), X-axis direction (11/21/31), nominal height (40), reference width (41), attachment (71), drawing direction (72)
|
|
147
|
+
- DIMENSION: block name (2), definition point (10/20/30), text midpoint (11/21/31), measurement points (13/23/33, 14/24/34), rotation (50), type (70)
|
|
63
148
|
|
|
64
|
-
|
|
149
|
+
Example:
|
|
65
150
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- BLOCK (DXF)
|
|
69
|
-
- ENDBLK (DXF)
|
|
151
|
+
```typescript
|
|
152
|
+
import { Helper } from '@linkiez/dxf-renew'
|
|
70
153
|
|
|
71
|
-
|
|
154
|
+
const helper = new Helper(dxfString)
|
|
155
|
+
const svg = helper.toSVG()
|
|
156
|
+
```
|
|
72
157
|
|
|
73
|
-
|
|
158
|
+
### SVG Rendering Integration Tests
|
|
74
159
|
|
|
75
|
-
|
|
76
|
-
- LWPOLYLINE, POLYLINE (+ VERTEX + SEQEND)
|
|
77
|
-
- ELLIPSE, SPLINE
|
|
78
|
-
- HATCH, SOLID, TRACE, REGION
|
|
79
|
-
- POINT
|
|
80
|
-
- TEXT, MTEXT
|
|
81
|
-
- DIMENSION, LEADER, MLEADER, TOLERANCE
|
|
82
|
-
- INSERT, ATTDEF, ATTRIB
|
|
83
|
-
- VIEWPORT
|
|
84
|
-
- IMAGE, UNDERLAY, WIPEOUT
|
|
85
|
-
- RAY, XLINE
|
|
86
|
-
- OLEFRAME, OLE2FRAME
|
|
87
|
-
- TABLE (entity)
|
|
160
|
+
Goal: validate final SVG output for real DXF fixtures:
|
|
88
161
|
|
|
89
|
-
|
|
162
|
+
`DXF fixture → parseString() → (optional denormalise) → toSVG() → SVG assertions`
|
|
90
163
|
|
|
91
|
-
|
|
164
|
+
Framework:
|
|
92
165
|
|
|
93
|
-
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
99
|
-
-
|
|
100
|
-
|
|
166
|
+
- Final rendering integration tests run in a real browser using Playwright.
|
|
167
|
+
|
|
168
|
+
Where tests live:
|
|
169
|
+
|
|
170
|
+
- Integration tests: `test/integration/**`
|
|
171
|
+
- Browser integration tests: `test/integration-browser/**`
|
|
172
|
+
- DXF fixtures: `test/resources/*.dxf`
|
|
173
|
+
|
|
174
|
+
Recommended assertions:
|
|
175
|
+
|
|
176
|
+
1. SVG well-formed envelope (`<svg>`, `</svg>`, `viewBox`)
|
|
177
|
+
2. Entity-specific elements (`<line>`, `<path>`, `<circle>`, `<text>`, `<image>`)
|
|
178
|
+
3. Critical attributes (e.g. `marker-start` / `marker-end` for DIMENSION)
|
|
179
|
+
4. Text content (when applicable)
|
|
180
|
+
5. “Does not throw” for a curated set of fixtures
|
|
181
|
+
|
|
182
|
+
Saved render artifacts (PNG):
|
|
183
|
+
|
|
184
|
+
- Browser integration tests should save a screenshot under `test/rendered/` for manual review.
|
|
185
|
+
- Prefer deterministic filenames tied to fixtures, e.g. `test/rendered/dimension-vertical.png`.
|
|
186
|
+
|
|
187
|
+
Handling non-deterministic IDs:
|
|
188
|
+
|
|
189
|
+
- Some SVG IDs are timestamp-based (e.g. DIMENSION arrow markers). Validate prefix-based patterns instead of exact IDs.
|
|
190
|
+
|
|
191
|
+
### Entity SVG Roadmap (Fixture → ezdxf → SVG Integration)
|
|
192
|
+
|
|
193
|
+
This roadmap is a repeatable checklist for each DXF entity:
|
|
194
|
+
|
|
195
|
+
- Confirm/produce a fixture in `test/resources/`.
|
|
196
|
+
- Validate it with ezdxf (see `docs/FIXTURE_VALIDATION_EZDXF.md`).
|
|
197
|
+
- Add/extend unit parsing tests.
|
|
198
|
+
- Add final SVG integration tests.
|
|
199
|
+
|
|
200
|
+
Template:
|
|
201
|
+
|
|
202
|
+
- Fixture: add or pick a DXF fixture in `test/resources/<entity>-<scenario>.dxf` (keep fixtures minimal).
|
|
203
|
+
- ezdxf validation: run `yarn validate:fixtures`, confirm the file loads, `$ACADVER` is present, and entity counts include your target entity.
|
|
204
|
+
- Unit tests: add unit parsing tests under `test/unit/`, assert minimum required fields for the entity type.
|
|
205
|
+
- SVG integration tests: add `test/integration-browser/<entity>-rendering.browser.spec.js`, assert SVG envelope + required elements/attributes + expected text content when applicable.
|
|
206
|
+
|
|
207
|
+
Saved PNG per entity (required):
|
|
208
|
+
|
|
209
|
+
- Every browser integration test should save a screenshot to `test/rendered/<fixture-name>.png`.
|
|
210
|
+
|
|
211
|
+
### DIMENSION Implementation Summary
|
|
212
|
+
|
|
213
|
+
The DIMENSION entity is implemented with support for the DIMSTYLE system, including parsing, storage, and SVG rendering.
|
|
214
|
+
|
|
215
|
+
Highlights:
|
|
216
|
+
|
|
217
|
+
- DIMSTYLE parsing in `src/handlers/tables.ts` (dozens of properties including arrow blocks, tolerances, alternate units).
|
|
218
|
+
- Rendering module `src/dimensionToSVG.ts` dispatches by dimension type and generates SVG markers for arrows.
|
|
219
|
+
- Color + lineweight support via DIMSTYLE values (dimension, extension, and text colors; line weights).
|
|
220
|
+
|
|
221
|
+
Dimension types supported in SVG rendering:
|
|
222
|
+
|
|
223
|
+
- Type 0/1 (linear): extension lines, dimension line, arrows, rotated text
|
|
224
|
+
- Type 2 (angular): arc dimension line, arrows, rotated text
|
|
225
|
+
- Type 3 (diameter): ⌀ symbol
|
|
226
|
+
- Type 4 (radius): R prefix
|
|
227
|
+
- Type 6 (ordinate): leader line and coordinate text
|
|
228
|
+
|
|
229
|
+
Optional features (not implemented): custom arrow blocks rendering, full tolerances/alternate units formatting, per-entity XDATA overrides.
|
|
230
|
+
|
|
231
|
+
## “Sitemap” / Checklist Source
|
|
232
|
+
|
|
233
|
+
- Primary navigation for implementation work: [docs/EZDXF_REFERENCE_SITEMAP.md](docs/EZDXF_REFERENCE_SITEMAP.md)
|
|
234
|
+
|
|
235
|
+
Note: do not embed large copies of Autodesk TOCs/spec text in this plan. Keep external links instead so this file stays maintainable.
|
|
101
236
|
|
|
102
237
|
## Current State (Repository Snapshot)
|
|
103
238
|
|
|
@@ -107,8 +242,8 @@ This section is intentionally short; it highlights gaps relevant to the migratio
|
|
|
107
242
|
|
|
108
243
|
Entity parsers currently exist for (see `src/handlers/entities.ts` and `src/handlers/entity/*`):
|
|
109
244
|
|
|
110
|
-
- Implemented: ARC, ATTDEF, ATTRIB, CIRCLE, DIMENSION, ELLIPSE, HATCH, INSERT, LINE, LWPOLYLINE, MTEXT, OLE2FRAME, POINT, POLYLINE, SOLID, SPLINE, TEXT, 3DFACE, VERTEX, VIEWPORT.
|
|
111
|
-
- Missing (not exhaustive):
|
|
245
|
+
- Implemented: ARC, ATTDEF, ATTRIB, CIRCLE, DIMENSION, ELLIPSE, HATCH, INSERT, LEADER, LINE, LWPOLYLINE, MTEXT, OLE2FRAME, POINT, POLYLINE, RAY, SHAPE, SOLID, SPLINE, TEXT, TOLERANCE, TRACE, WIPEOUT, XLINE, 3DFACE, VERTEX, VIEWPORT.
|
|
246
|
+
- Missing (not exhaustive): SEQEND handling robustness.
|
|
112
247
|
|
|
113
248
|
### Tables
|
|
114
249
|
|
|
@@ -121,8 +256,8 @@ Entity parsers currently exist for (see `src/handlers/entities.ts` and `src/hand
|
|
|
121
256
|
|
|
122
257
|
`src/handlers/objects.ts` currently parses:
|
|
123
258
|
|
|
124
|
-
- Implemented: LAYOUT (partial).
|
|
125
|
-
- Missing from Autodesk TOC subset above:
|
|
259
|
+
- Implemented: LAYOUT (partial), DICTIONARY, XRECORD, DIMASSOC, FIELD, IMAGEDEF (+ reactor), UNDERLAY definitions.
|
|
260
|
+
- Missing from Autodesk TOC subset above: TABLESTYLE, GROUP, etc.
|
|
126
261
|
|
|
127
262
|
## Project Analysis (Code-Backed)
|
|
128
263
|
|
|
@@ -228,6 +363,8 @@ There is already substantial fixture coverage in `test/resources/*.dxf` and unit
|
|
|
228
363
|
|
|
229
364
|
- Rendering tests exist for `toSVG`, `toPolylines`, dimension/text, blocks/inserts, and hatches.
|
|
230
365
|
- Use this existing corpus to gate each milestone; add only minimal new fixtures per newly-supported feature.
|
|
366
|
+
- When fixtures become too complex, brittle, or hard to assert against, it is acceptable to replace them with simpler, targeted fixtures (including ezdxf-generated ones) as long as the test still covers the intended behavior.
|
|
367
|
+
- After adding or regenerating fixtures, run `yarn validate:fixtures` to ensure DXF structure is sound.
|
|
231
368
|
|
|
232
369
|
## Milestones
|
|
233
370
|
|
|
@@ -242,6 +379,8 @@ There is already substantial fixture coverage in `test/resources/*.dxf` and unit
|
|
|
242
379
|
- PR 0.1: Add/confirm one “golden” unit test per public API (`parseString`, `toPolylines`, `toSVG`).
|
|
243
380
|
- PR 0.2: Add a test-only strict mode helper (e.g., fail on unknown entity/table/object types) without changing the runtime default behavior.
|
|
244
381
|
- PR 0.3: Add 1–3 new fixtures only if existing fixtures don’t cover a targeted feature.
|
|
382
|
+
- If a fixture is too complex for stable assertions, prefer a smaller, focused fixture generated via ezdxf.
|
|
383
|
+
- It is OK to replace or simplify existing fixtures if they remain representative of the behavior under test.
|
|
245
384
|
|
|
246
385
|
- Add/confirm a single “golden” pipeline test per API surface:
|
|
247
386
|
- `parseString()` parses representative DXFs without throwing.
|
|
@@ -330,7 +469,7 @@ There is already substantial fixture coverage in `test/resources/*.dxf` and unit
|
|
|
330
469
|
|
|
331
470
|
1. Implement missing entity handlers (prioritized)
|
|
332
471
|
|
|
333
|
-
Annotation:
|
|
472
|
+
Annotation: MLEADER. Geometry: REGION. Reference: IMAGE, UNDERLAY. Legacy: OLEFRAME. Table-in-entities: TABLE (entity). Optional/edge: MLINE.
|
|
334
473
|
|
|
335
474
|
1. Ensure common fields are handled consistently
|
|
336
475
|
|
|
@@ -391,27 +530,29 @@ Legend:
|
|
|
391
530
|
|
|
392
531
|
### A.1 Entities (2D-critical)
|
|
393
532
|
|
|
394
|
-
Already parsed (handlers exist): LINE, LWPOLYLINE, POLYLINE, ARC, CIRCLE, ELLIPSE, SPLINE, TEXT, MTEXT, DIMENSION, INSERT, ATTDEF, ATTRIB, HATCH, SOLID, POINT, VIEWPORT, OLE2FRAME.
|
|
533
|
+
Already parsed (handlers exist): LINE, LWPOLYLINE, POLYLINE, ARC, CIRCLE, ELLIPSE, SPLINE, TEXT, MTEXT, DIMENSION, INSERT, ATTDEF, ATTRIB, HATCH, SOLID, TRACE, POINT, VIEWPORT, OLE2FRAME, LEADER, RAY, XLINE, SHAPE, TOLERANCE, WIPEOUT.
|
|
534
|
+
|
|
535
|
+
Also parsed (parse-only / safe ignore): MLEADER, MLINE, OLEFRAME, REGION, TABLE (entity).
|
|
395
536
|
|
|
396
537
|
The items below are the main gaps to reach “complete 2D” as defined in this plan.
|
|
397
538
|
|
|
398
539
|
| Entity | Parse | Render (SVG) | Render (Polylines) | Block-safe | Minimal implementation checklist |
|
|
399
540
|
| --- | --- | --- | --- | --- | --- |
|
|
400
541
|
| SEQEND | Sentinel only | N/A | N/A | N/A | Add `src/handlers/entity/seqend.ts` (optional) or harden sequencing in `src/handlers/entities.ts` + add fixture that stresses POLYLINE/VERTEX/SEQEND ordering |
|
|
401
|
-
| LEADER |
|
|
402
|
-
| MLEADER |
|
|
403
|
-
| TOLERANCE |
|
|
404
|
-
| IMAGE |
|
|
405
|
-
| UNDERLAY |
|
|
406
|
-
| WIPEOUT |
|
|
407
|
-
| RAY |
|
|
408
|
-
| XLINE |
|
|
409
|
-
| OLEFRAME |
|
|
410
|
-
| TRACE |
|
|
411
|
-
| REGION |
|
|
412
|
-
| TABLE (entity) |
|
|
413
|
-
| SHAPE |
|
|
414
|
-
| MLINE |
|
|
542
|
+
| LEADER | Yes | Yes | Yes | No | Implemented (minimal polyline support + SVG routing) |
|
|
543
|
+
| MLEADER | Yes | No | No | No | Implemented parse-only + safe ignore in rendering |
|
|
544
|
+
| TOLERANCE | Yes | Yes | No | No | Implemented (SVG text fallback only) |
|
|
545
|
+
| IMAGE | Yes | No | No | No | Add `src/types/image-entity.ts`; add `src/handlers/entity/image.ts`; add OBJECTS: IMAGEDEF/IMAGEDEF_REACTOR; render as placeholder rect or ignore safely |
|
|
546
|
+
| UNDERLAY | Yes | No | No | No | Add `src/types/underlay-entity.ts`; add `src/handlers/entity/dwfUnderlay.ts` + `src/handlers/entity/dgnUnderlay.ts`; add OBJECTS: UNDERLAYDEFINITION; render placeholder/ignore |
|
|
547
|
+
| WIPEOUT | Yes | Yes | Yes | No | Implemented (outline-only; masking not yet implemented) |
|
|
548
|
+
| RAY | Yes | Yes | Yes | No | Implemented (finite fallback in polyline/SVG) |
|
|
549
|
+
| XLINE | Yes | Yes | Yes | No | Implemented (finite fallback in polyline/SVG) |
|
|
550
|
+
| OLEFRAME | Yes | No | No | No | Implemented parse-only + safe ignore in rendering |
|
|
551
|
+
| TRACE | Yes | Yes | Yes | No | Implemented (filled SVG + closed polyline) |
|
|
552
|
+
| REGION | Yes | No | No | No | Implemented parse-only + safe ignore in rendering |
|
|
553
|
+
| TABLE (entity) | Yes | No | No | No | Implemented parse-only + safe ignore in rendering |
|
|
554
|
+
| SHAPE | Yes | Yes | Yes | No | Implemented (minimal polyline + SVG text fallback) |
|
|
555
|
+
| MLINE | Yes | No | No | No | Implemented parse-only + safe ignore in rendering |
|
|
415
556
|
|
|
416
557
|
### A.2 Tables (2D-relevant)
|
|
417
558
|
|
|
@@ -426,11 +567,12 @@ The items below are the main gaps to reach “complete 2D” as defined in this
|
|
|
426
567
|
|
|
427
568
|
| Object | Current status | Primary file(s) to change | Minimal checklist |
|
|
428
569
|
| --- | --- | --- | --- |
|
|
429
|
-
| DICTIONARY |
|
|
430
|
-
| XRECORD |
|
|
431
|
-
| DIMASSOC |
|
|
432
|
-
| IMAGEDEF / IMAGEDEF_REACTOR |
|
|
433
|
-
|
|
|
570
|
+
| DICTIONARY | Implemented | `src/handlers/objects.ts` (+ new types file if desired) | Group objects by `0`; add DICTIONARY parser; store by handle for lookup |
|
|
571
|
+
| XRECORD | Implemented | `src/handlers/objects.ts` | Add XRECORD parser; preserve raw records for downstream consumers |
|
|
572
|
+
| DIMASSOC | Implemented | `src/handlers/objects.ts` | Implemented minimal parse; preserves raw tuples for downstream consumers |
|
|
573
|
+
| IMAGEDEF / IMAGEDEF_REACTOR | Implemented | `src/handlers/objects.ts` | Parse enough to resolve IMAGE entity references; do not crash if external files missing |
|
|
574
|
+
| UNDERLAYDEFINITION | Implemented | `src/handlers/objects.ts` | Parse enough to resolve DWFUNDERLAY/DGNUNDERLAY references; do not crash if external files missing |
|
|
575
|
+
| FIELD | Implemented | `src/handlers/objects.ts` | Implemented minimal parse; preserves raw tuples for downstream consumers |
|
|
434
576
|
| TABLESTYLE | Missing | `src/handlers/objects.ts` | Parse style basics; used later for TABLE entity rendering |
|
|
435
577
|
| GROUP | Missing | `src/handlers/objects.ts` | Parse group membership; safe ignore if not used |
|
|
436
578
|
|
|
@@ -447,10 +589,10 @@ This appendix provides an explicit sequence of PRs. The intent is to keep each P
|
|
|
447
589
|
|
|
448
590
|
### B.1 Recommended order (high value first)
|
|
449
591
|
|
|
450
|
-
- **Stabilize existing behavior**: PR B1.1 (POLYLINE/VERTEX/SEQEND sequencing), PR B1.2 (block basepoint for TEXT/MTEXT/DIMENSION).
|
|
451
|
-
- **Unblock references and metadata**: PR B1.3 (OBJECTS dispatch + DICTIONARY), PR B1.4 (XRECORD).
|
|
452
|
-
- **Enable images/underlays**: PR B1.5 (IMAGEDEF / IMAGEDEF_REACTOR), PR B1.6 (IMAGE entity), PR B1.7 (UNDERLAY defs + UNDERLAY entity).
|
|
453
|
-
- **Add remaining common 2D annotation**: PR B1.8 (LEADER), PR B1.9 (TOLERANCE), PR B1.10 (DIMASSOC), PR B1.11 (MLEADER).
|
|
592
|
+
- **Stabilize existing behavior**: ✅ PR B1.1 (POLYLINE/VERTEX/SEQEND sequencing), ✅ PR B1.2 (block basepoint for TEXT/MTEXT/DIMENSION).
|
|
593
|
+
- **Unblock references and metadata**: ✅ PR B1.3 (OBJECTS dispatch + DICTIONARY), ✅ PR B1.4 (XRECORD).
|
|
594
|
+
- **Enable images/underlays**: ✅ PR B1.5 (IMAGEDEF / IMAGEDEF_REACTOR), ✅ PR B1.6 (IMAGE entity), ✅ PR B1.7 (UNDERLAY defs + UNDERLAY entity).
|
|
595
|
+
- **Add remaining common 2D annotation**: ✅ PR B1.8 (LEADER), ✅ PR B1.9 (TOLERANCE), ✅ PR B1.10 (DIMASSOC), ✅ PR B1.11 (MLEADER).
|
|
454
596
|
|
|
455
597
|
### B.2 PR templates by feature type
|
|
456
598
|
|
|
@@ -484,20 +626,20 @@ This table expands Appendix A into explicit PR steps.
|
|
|
484
626
|
|
|
485
627
|
| Entity | PR 1 (Parse) | PR 2 (SVG) | PR 3 (Polylines) | PR 4 (Block-safe) |
|
|
486
628
|
| --- | --- | --- | --- | --- |
|
|
487
|
-
| LEADER |
|
|
488
|
-
| MLEADER |
|
|
489
|
-
| TOLERANCE |
|
|
629
|
+
| LEADER | Done | Done | Done | Optional |
|
|
630
|
+
| MLEADER | Done (parse-only) | Safe ignore or placeholder first | N/A | Later, after DICTIONARY/XRECORD/DIMASSOC coverage |
|
|
631
|
+
| TOLERANCE | Done | Done (text fallback) | N/A | Optional |
|
|
490
632
|
| IMAGE | Add IMAGEDEF(+reactor) objects, then IMAGE entity parse + tests | Placeholder rect/image element or safe ignore | N/A | Update `denormalise` for block-contained images |
|
|
491
633
|
| UNDERLAY | Add underlay defs objects, then UNDERLAY entity parse + tests | Placeholder | N/A | Optional |
|
|
492
|
-
| WIPEOUT |
|
|
493
|
-
| RAY |
|
|
494
|
-
| XLINE |
|
|
495
|
-
| OLEFRAME |
|
|
496
|
-
| TRACE |
|
|
497
|
-
| REGION |
|
|
498
|
-
| TABLE (entity) |
|
|
499
|
-
| SHAPE |
|
|
500
|
-
| MLINE |
|
|
634
|
+
| WIPEOUT | Done | Done (outline-only fallback) | Done | Optional |
|
|
635
|
+
| RAY | Done | Done | Done | Optional |
|
|
636
|
+
| XLINE | Done | Done | Done | Optional |
|
|
637
|
+
| OLEFRAME | Done | Placeholder or safe ignore | N/A | Optional |
|
|
638
|
+
| TRACE | Done | Done | Done | Optional |
|
|
639
|
+
| REGION | Done (parse-only) | Safe ignore first | Safe ignore | N/A |
|
|
640
|
+
| TABLE (entity) | Done (parse-only) | Safe ignore/placeholder | N/A | Optional |
|
|
641
|
+
| SHAPE | Done | Done (text fallback) | Done | N/A |
|
|
642
|
+
| MLINE | Done (parse-only) | Safe ignore first | N/A | N/A |
|
|
501
643
|
|
|
502
644
|
### B.4 Concrete PR checklist for missing tables
|
|
503
645
|
|
|
@@ -512,6 +654,6 @@ This table expands Appendix A into explicit PR steps.
|
|
|
512
654
|
- PR: Add XRECORD support + tests.
|
|
513
655
|
- PR: Add DIMASSOC support + tests.
|
|
514
656
|
- PR: Add IMAGEDEF / IMAGEDEF_REACTOR support + tests.
|
|
515
|
-
- PR: Add FIELD support + tests.
|
|
657
|
+
- ✅ PR: Add FIELD support + tests.
|
|
516
658
|
- PR: Add TABLESTYLE support + tests.
|
|
517
659
|
- PR: Add GROUP support + tests.
|