@bill_nee/dwg-reader 0.0.0-stage → 1.0.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 (99) hide show
  1. package/LICENSE +615 -0
  2. package/cordis.patch.yml +3 -0
  3. package/icon.svg +15 -0
  4. package/lib/index.js +355 -0
  5. package/locale/en.json +6 -0
  6. package/locale/zh.json +6 -0
  7. package/package.json +32 -4
  8. package/vendor/libredwg-web/lib/converter/converter.js +1102 -0
  9. package/vendor/libredwg-web/lib/converter/dwgColorToMLeaderRawColor.js +55 -0
  10. package/vendor/libredwg-web/lib/converter/entityConverter.js +2050 -0
  11. package/vendor/libredwg-web/lib/converter/index.js +3 -0
  12. package/vendor/libredwg-web/lib/converter/utils.js +46 -0
  13. package/vendor/libredwg-web/lib/database/classes/class.js +2 -0
  14. package/vendor/libredwg-web/lib/database/classes/index.js +2 -0
  15. package/vendor/libredwg-web/lib/database/codepage.js +101 -0
  16. package/vendor/libredwg-web/lib/database/common.js +2 -0
  17. package/vendor/libredwg-web/lib/database/database.js +2 -0
  18. package/vendor/libredwg-web/lib/database/entities/3dface.js +2 -0
  19. package/vendor/libredwg-web/lib/database/entities/arc.js +2 -0
  20. package/vendor/libredwg-web/lib/database/entities/arcAlignedText.js +2 -0
  21. package/vendor/libredwg-web/lib/database/entities/attdef.js +2 -0
  22. package/vendor/libredwg-web/lib/database/entities/attrib.js +2 -0
  23. package/vendor/libredwg-web/lib/database/entities/circle.js +2 -0
  24. package/vendor/libredwg-web/lib/database/entities/dimension.js +70 -0
  25. package/vendor/libredwg-web/lib/database/entities/ellipse.js +2 -0
  26. package/vendor/libredwg-web/lib/database/entities/entity.js +2 -0
  27. package/vendor/libredwg-web/lib/database/entities/hatch.js +54 -0
  28. package/vendor/libredwg-web/lib/database/entities/image.js +2 -0
  29. package/vendor/libredwg-web/lib/database/entities/index.js +38 -0
  30. package/vendor/libredwg-web/lib/database/entities/insert.js +2 -0
  31. package/vendor/libredwg-web/lib/database/entities/leader.js +2 -0
  32. package/vendor/libredwg-web/lib/database/entities/line.js +2 -0
  33. package/vendor/libredwg-web/lib/database/entities/lwpolyline.js +2 -0
  34. package/vendor/libredwg-web/lib/database/entities/mline.js +2 -0
  35. package/vendor/libredwg-web/lib/database/entities/mtext.js +2 -0
  36. package/vendor/libredwg-web/lib/database/entities/multileader.js +2 -0
  37. package/vendor/libredwg-web/lib/database/entities/ole2frame.js +2 -0
  38. package/vendor/libredwg-web/lib/database/entities/oleframe.js +2 -0
  39. package/vendor/libredwg-web/lib/database/entities/point.js +2 -0
  40. package/vendor/libredwg-web/lib/database/entities/polyline.js +19 -0
  41. package/vendor/libredwg-web/lib/database/entities/proxy.js +10 -0
  42. package/vendor/libredwg-web/lib/database/entities/ray.js +2 -0
  43. package/vendor/libredwg-web/lib/database/entities/section.js +2 -0
  44. package/vendor/libredwg-web/lib/database/entities/shape.js +2 -0
  45. package/vendor/libredwg-web/lib/database/entities/solid.js +2 -0
  46. package/vendor/libredwg-web/lib/database/entities/solid3d.js +2 -0
  47. package/vendor/libredwg-web/lib/database/entities/spline.js +2 -0
  48. package/vendor/libredwg-web/lib/database/entities/table.js +2 -0
  49. package/vendor/libredwg-web/lib/database/entities/text.js +23 -0
  50. package/vendor/libredwg-web/lib/database/entities/tolerance.js +2 -0
  51. package/vendor/libredwg-web/lib/database/entities/trace.js +2 -0
  52. package/vendor/libredwg-web/lib/database/entities/vertex.js +2 -0
  53. package/vendor/libredwg-web/lib/database/entities/viewport.js +2 -0
  54. package/vendor/libredwg-web/lib/database/entities/wipeout.js +2 -0
  55. package/vendor/libredwg-web/lib/database/entities/xline.js +2 -0
  56. package/vendor/libredwg-web/lib/database/header/header.js +2 -0
  57. package/vendor/libredwg-web/lib/database/header/index.js +3 -0
  58. package/vendor/libredwg-web/lib/database/header/variables.js +217 -0
  59. package/vendor/libredwg-web/lib/database/index.js +12 -0
  60. package/vendor/libredwg-web/lib/database/objects/common.js +2 -0
  61. package/vendor/libredwg-web/lib/database/objects/dictionary.js +19 -0
  62. package/vendor/libredwg-web/lib/database/objects/imageDef.js +2 -0
  63. package/vendor/libredwg-web/lib/database/objects/index.js +11 -0
  64. package/vendor/libredwg-web/lib/database/objects/layerFilter.js +2 -0
  65. package/vendor/libredwg-web/lib/database/objects/layerIndex.js +2 -0
  66. package/vendor/libredwg-web/lib/database/objects/layout.js +2 -0
  67. package/vendor/libredwg-web/lib/database/objects/mleaderStyle.js +2 -0
  68. package/vendor/libredwg-web/lib/database/objects/plotSetting.js +2 -0
  69. package/vendor/libredwg-web/lib/database/objects/spatialFilter.js +2 -0
  70. package/vendor/libredwg-web/lib/database/objects/xrecord.js +2 -0
  71. package/vendor/libredwg-web/lib/database/shared/index.js +2 -0
  72. package/vendor/libredwg-web/lib/database/shared/xdata.js +2 -0
  73. package/vendor/libredwg-web/lib/database/tables/appId.js +2 -0
  74. package/vendor/libredwg-web/lib/database/tables/blockRecord.js +2 -0
  75. package/vendor/libredwg-web/lib/database/tables/dimStyle.js +2 -0
  76. package/vendor/libredwg-web/lib/database/tables/index.js +9 -0
  77. package/vendor/libredwg-web/lib/database/tables/layer.js +2 -0
  78. package/vendor/libredwg-web/lib/database/tables/ltype.js +2 -0
  79. package/vendor/libredwg-web/lib/database/tables/style.js +2 -0
  80. package/vendor/libredwg-web/lib/database/tables/table.js +2 -0
  81. package/vendor/libredwg-web/lib/database/tables/vport.js +2 -0
  82. package/vendor/libredwg-web/lib/database/textEscapes.js +19 -0
  83. package/vendor/libredwg-web/lib/database/version.js +260 -0
  84. package/vendor/libredwg-web/lib/index.js +4 -0
  85. package/vendor/libredwg-web/lib/libredwg.js +1271 -0
  86. package/vendor/libredwg-web/lib/svg/box2d.js +104 -0
  87. package/vendor/libredwg-web/lib/svg/bspline.js +95 -0
  88. package/vendor/libredwg-web/lib/svg/color.js +371 -0
  89. package/vendor/libredwg-web/lib/svg/index.js +2 -0
  90. package/vendor/libredwg-web/lib/svg/polyline.js +70 -0
  91. package/vendor/libredwg-web/lib/svg/svgConverter.js +540 -0
  92. package/vendor/libredwg-web/lib/svg/transformBoundingBoxAndElement.js +20 -0
  93. package/vendor/libredwg-web/lib/svg/vector.js +27 -0
  94. package/vendor/libredwg-web/lib/types/common.js +2 -0
  95. package/vendor/libredwg-web/lib/types/enums.js +390 -0
  96. package/vendor/libredwg-web/lib/types/index.js +3 -0
  97. package/vendor/libredwg-web/wasm/libredwg-web.js +2 -0
  98. package/vendor/libredwg-web/wasm/libredwg-web.wasm +0 -0
  99. package/README.md +0 -3
package/lib/index.js ADDED
@@ -0,0 +1,355 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import { LibreDwg, Dwg_File_Type, DwgCodePage } from "../vendor/libredwg-web/lib/index.js";
3
+
4
+ const WASM_DIR = fileURLToPath(new URL("../vendor/libredwg-web/wasm", import.meta.url));
5
+ const MAX_DWG_BYTES = 512 * 1024 * 1024; // 512 MB 上限,超大图纸会先于 WASM 内存耗尽给出明确报错
6
+ const MAX_ENTITY_DETAIL = 2000;
7
+
8
+ let libreDwgPromise;
9
+
10
+ function getLibreDwg() {
11
+ if (!libreDwgPromise) {
12
+ libreDwgPromise = LibreDwg.create(WASM_DIR);
13
+ }
14
+ return libreDwgPromise;
15
+ }
16
+
17
+ async function sessionResolveOptions(ctx, exec) {
18
+ const cwd =
19
+ exec.agent === undefined
20
+ ? undefined
21
+ : await ctx.workingDirectory.ensure(exec.agent, exec.signal).catch(() => undefined);
22
+ return {
23
+ ...(cwd !== undefined ? { cwd } : {}),
24
+ signal: exec.signal,
25
+ };
26
+ }
27
+
28
+ function dateToIso(value) {
29
+ if (value instanceof Date) return value.toISOString();
30
+ return value ? String(value) : null;
31
+ }
32
+
33
+ function pointToObj(point) {
34
+ if (!point) return null;
35
+ return { x: point.x, y: point.y, z: point.z };
36
+ }
37
+
38
+ /**
39
+ * 把返回值收敛为纯 JSON:丢掉 undefined 属性,避免 snapshot 校验失败。
40
+ */
41
+ function toJson(value) {
42
+ return JSON.parse(JSON.stringify(value));
43
+ }
44
+
45
+ function buildReadDwgTool(ctx) {
46
+ return {
47
+ name: "read_dwg",
48
+ description:
49
+ "直接读取 AutoCAD DWG 图纸文件(基于 libredwg WASM 解析,无需安装 AutoCAD)。" +
50
+ "返回图纸版本、编码、图层表、块数量、实体统计(按类型计数)与可选实体明细;" +
51
+ "可选导出 SVG 预览。适用于查看 DWG 的图层/实体构成、核对图纸信息。注意:DXF 暂不支持," +
52
+ "大图纸(>100MB)可能因 WASM 内存不足失败。",
53
+ parameters: {
54
+ type: "object",
55
+ additionalProperties: true,
56
+ properties: {
57
+ file_path: {
58
+ type: "string",
59
+ description: "DWG 文件路径(绝对路径或相对当前工作目录)。",
60
+ },
61
+ entities: {
62
+ type: "boolean",
63
+ description: "是否返回实体明细列表(默认 false,只返回统计)。",
64
+ },
65
+ entity_limit: {
66
+ type: "integer",
67
+ description: `实体明细最多返回条数(默认 200,上限 ${MAX_ENTITY_DETAIL})。`,
68
+ },
69
+ export_svg: {
70
+ type: "boolean",
71
+ description: "是否同时导出 SVG 预览文件(默认 false)。",
72
+ },
73
+ svg_output_path: {
74
+ type: "string",
75
+ description: "SVG 输出路径;缺省时写到 DWG 同目录下的同名 .svg 文件。",
76
+ },
77
+ },
78
+ required: ["file_path"],
79
+ },
80
+ output: {
81
+ schema: {
82
+ type: "object",
83
+ additionalProperties: true,
84
+ properties: {
85
+ path: { type: "string", description: "解析后的文件路径。" },
86
+ fileName: { type: "string", description: "文件名。" },
87
+ fileSizeBytes: { type: "integer", description: "文件字节数。" },
88
+ versionType: { type: "string", description: "DWG 版本代号(如 AC1018 / r2007)。" },
89
+ versionDescription: { type: "string", description: "版本描述(如 AutoCAD 2007)。" },
90
+ codepage: { type: "integer", description: "编码页枚举值(未知为 -1)。" },
91
+ codepageName: { type: "string", description: "编码页名称(如 CP_ANSI_936)。" },
92
+ header: { type: "object", additionalProperties: true, description: "图头关键变量。" },
93
+ layerCount: { type: "integer", description: "图层数量。" },
94
+ layers: {
95
+ type: "array",
96
+ items: { type: "object", additionalProperties: true },
97
+ description: "图层表(名称/颜色/线型/开关状态)。",
98
+ },
99
+ blockCount: { type: "integer", description: "块记录数量。" },
100
+ entityCount: { type: "integer", description: "实体总数。" },
101
+ entityTypeCounts: {
102
+ type: "object",
103
+ additionalProperties: true,
104
+ description: "按实体类型统计数量(如 { LINE: 120, TEXT: 8 })。",
105
+ },
106
+ unknownEntityCount: { type: "integer", description: "无法识别类型而被跳过的实体数。" },
107
+ thumbnailPresent: { type: "boolean", description: "图纸是否带缩略图。" },
108
+ entities: {
109
+ type: "array",
110
+ items: { type: "object", additionalProperties: true },
111
+ description: "实体明细(仅当 entities=true 时非空)。",
112
+ },
113
+ entitiesTruncated: { type: "boolean", description: "实体明细是否被截断。" },
114
+ svgPath: {
115
+ oneOf: [{ type: "string" }, { type: "null" }],
116
+ description: "导出的 SVG 文件路径;未导出时为 null。",
117
+ },
118
+ },
119
+ },
120
+ render: (args, value) => {
121
+ const lines = [];
122
+ lines.push(`<path>${value.path}</path>`);
123
+ lines.push(`<type>dwg</type>`);
124
+ const sizeMb = (value.fileSizeBytes / 1024 / 1024).toFixed(2);
125
+ lines.push(`<content>已解析 DWG:${value.fileName}(${sizeMb} MB)`);
126
+ lines.push(`版本:${value.versionDescription}(${value.versionType})`);
127
+ lines.push(`编码:${value.codepageName}`);
128
+ lines.push(`图层:${value.layerCount} 个${value.layers.length ? " — " + value.layers.map((l) => l.name).join(", ") : ""}`);
129
+ lines.push(`块记录:${value.blockCount} 个;实体:${value.entityCount} 个`);
130
+ const typeLines = Object.entries(value.entityTypeCounts)
131
+ .sort((a, b) => b[1] - a[1])
132
+ .slice(0, 20)
133
+ .map(([t, n]) => `${t} ${n}`)
134
+ .join(",");
135
+ if (typeLines) lines.push(`实体构成:${typeLines}${Object.keys(value.entityTypeCounts).length > 20 ? ",…" : ""}`);
136
+ if (value.unknownEntityCount) lines.push(`未识别实体:${value.unknownEntityCount} 个`);
137
+ if (value.header && value.header.extmin && value.header.extmax) {
138
+ lines.push(
139
+ `图幅范围:X ${value.header.extmin.x}~${value.header.extmax.x},Y ${value.header.extmin.y}~${value.header.extmax.y}`
140
+ );
141
+ }
142
+ if (value.svgPath) lines.push(`SVG 预览:${value.svgPath}`);
143
+ if (value.entities && value.entities.length) {
144
+ lines.push(`实体明细(${value.entities.length}${value.entitiesTruncated ? ",已截断" : ""}):`);
145
+ const shown = value.entities.slice(0, 50);
146
+ for (const [i, e] of shown.entries()) {
147
+ lines.push(
148
+ ` ${i + 1}. ${e.type} handle=${e.handle} layer=${e.layer}` +
149
+ (e.colorIndex != null ? ` color=${e.colorIndex}` : "") +
150
+ (e.lineType != null ? ` linetype=${e.lineType}` : "") +
151
+ (e.isInPaperSpace ? " (图纸空间)" : "")
152
+ );
153
+ }
154
+ if (value.entities.length > shown.length) lines.push(` …(其余 ${value.entities.length - shown.length} 条未显示)`);
155
+ }
156
+ lines.push(`</content>`);
157
+ return [{ type: "text", text: lines.join("\n") }];
158
+ },
159
+ presentationMeta: () => null,
160
+ },
161
+ isConcurrencySafe: () => false, // WASM 单例 + tmp.dwg 固定文件名,串行执行
162
+ presentCall: (args) => ({
163
+ card: "generic",
164
+ title: `读取 DWG ${args.file_path || "(未指定路径)"}`,
165
+ kind: "read",
166
+ locations: [{ path: args.file_path || "" }],
167
+ }),
168
+ presentResult: (args, result) => {
169
+ if (result && result.isError) return undefined;
170
+ return {
171
+ card: "generic",
172
+ title: `DWG 解析完成:${args.file_path || ""}`,
173
+ kind: "read",
174
+ locations: [{ path: args.file_path || "" }],
175
+ };
176
+ },
177
+ async execute(args, exec) {
178
+ if (typeof args !== "object" || args === null) {
179
+ throw new Error(`invalid arguments: expected an object with a "file_path" string`);
180
+ }
181
+ if (typeof args.file_path !== "string" || !args.file_path.trim()) {
182
+ throw new Error('invalid arguments: "file_path" must be a non-empty string');
183
+ }
184
+ if (args.entities !== undefined && typeof args.entities !== "boolean") {
185
+ throw new Error('invalid arguments: "entities" must be a boolean');
186
+ }
187
+ if (args.export_svg !== undefined && typeof args.export_svg !== "boolean") {
188
+ throw new Error('invalid arguments: "export_svg" must be a boolean');
189
+ }
190
+ if (args.entity_limit !== undefined && (typeof args.entity_limit !== "number" || !Number.isInteger(args.entity_limit))) {
191
+ throw new Error('invalid arguments: "entity_limit" must be an integer');
192
+ }
193
+ if (args.svg_output_path !== undefined && typeof args.svg_output_path !== "string") {
194
+ throw new Error('invalid arguments: "svg_output_path" must be a string');
195
+ }
196
+
197
+ const resolveOptions = await sessionResolveOptions(ctx, exec);
198
+ const target = await ctx.fs.resolve(args.file_path.trim(), resolveOptions);
199
+ const info = await ctx.fs.stat(target, exec.signal);
200
+ const displayPath = ctx.fs.processPath(target);
201
+ if (!info) {
202
+ ctx.emit("fs/observed", target, { kind: "absent" }, exec);
203
+ throw new Error(`cannot read "${displayPath}": not found`);
204
+ }
205
+ if (info.type !== "file") {
206
+ throw new Error(`cannot read "${displayPath}": not a regular file`);
207
+ }
208
+ if (info.size !== undefined && info.size > MAX_DWG_BYTES) {
209
+ throw new Error(
210
+ `cannot read "${displayPath}": file is ${(info.size / 1024 / 1024).toFixed(1)} MB, ` +
211
+ `超过 ${MAX_DWG_BYTES / 1024 / 1024} MB 上限`
212
+ );
213
+ }
214
+ const bytes = await ctx.fs.readBytes(target, exec.signal, MAX_DWG_BYTES);
215
+ ctx.emit("fs/observed", target, { kind: "present", version: info.version }, exec);
216
+
217
+ if (displayPath.toLowerCase().endsWith(".dxf")) {
218
+ throw new Error(`cannot read "${displayPath}": DXF 暂不受支持(本插件当前仅解析 DWG)`);
219
+ }
220
+
221
+ let dwg;
222
+ try {
223
+ dwg = await getLibreDwg();
224
+ } catch (error) {
225
+ throw new Error(`cannot read "${displayPath}": 初始化 DWG 解析引擎失败: ${error.message}`);
226
+ }
227
+
228
+ const dataPtr = dwg.dwg_read_data(bytes, Dwg_File_Type.DWG);
229
+ if (!dataPtr) {
230
+ throw new Error(`cannot read "${displayPath}": not a valid DWG file (decode failed)`);
231
+ }
232
+ try {
233
+ const version = dwg.dwg_get_version_type(dataPtr) || {};
234
+ const codepage = dwg.dwg_get_codepage(dataPtr);
235
+ const converted = dwg.convertEx(dataPtr);
236
+ const database = converted.database;
237
+ const stats = converted.stats || {};
238
+
239
+ if (!database || (!database.entities.length && !database.tables.LAYER.entries.length)) {
240
+ throw new Error(`cannot read "${displayPath}": 未解析出任何图层或实体,可能不是有效的 DWG`);
241
+ }
242
+
243
+ const header = database.header || {};
244
+ const headerSummary = {};
245
+ if (header.ACADVER != null) headerSummary.acadver = String(header.ACADVER);
246
+ if (header.DWGCODEPAGE != null) headerSummary.dwgcodepage = String(header.DWGCODEPAGE);
247
+ if (header.INSUNITS != null) headerSummary.insunits = header.INSUNITS;
248
+ if (header.EXTMIN) headerSummary.extmin = pointToObj(header.EXTMIN);
249
+ if (header.EXTMAX) headerSummary.extmax = pointToObj(header.EXTMAX);
250
+ const tdc = dateToIso(header.TDCREATE);
251
+ const tdu = dateToIso(header.TDUPDATE);
252
+ if (tdc) headerSummary.created = tdc;
253
+ if (tdu) headerSummary.updated = tdu;
254
+ if (header.CLAYER) headerSummary.currentLayer = String(header.CLAYER);
255
+
256
+ const layers = database.tables.LAYER.entries.map((layer) => ({
257
+ name: layer.name,
258
+ colorIndex: typeof layer.colorIndex === "number" ? layer.colorIndex : null,
259
+ colorName: layer.colorName != null ? layer.colorName : null,
260
+ lineType: layer.lineType != null ? layer.lineType : null,
261
+ frozen: !!layer.frozen,
262
+ off: !!layer.off,
263
+ locked: !!layer.locked,
264
+ plot: layer.plotFlag != null ? !!layer.plotFlag : null,
265
+ }));
266
+
267
+ const entityTypeCounts = {};
268
+ for (const entity of database.entities) {
269
+ const t = entity.type || "UNKNOWN";
270
+ entityTypeCounts[t] = (entityTypeCounts[t] || 0) + 1;
271
+ }
272
+
273
+ const limit = Math.min(Math.max(1, args.entity_limit || 200), MAX_ENTITY_DETAIL);
274
+ const detailEntities = args.entities ? database.entities.slice(0, limit) : [];
275
+ const entities = detailEntities.map((entity) => ({
276
+ type: entity.type || "UNKNOWN",
277
+ handle: entity.handle != null ? entity.handle : null,
278
+ layer: entity.layer != null ? entity.layer : null,
279
+ colorIndex: typeof entity.colorIndex === "number" ? entity.colorIndex : null,
280
+ lineType: entity.lineType != null ? entity.lineType : null,
281
+ isInPaperSpace: !!entity.isInPaperSpace,
282
+ }));
283
+
284
+ let svgPath = null;
285
+ if (args.export_svg) {
286
+ let svgText;
287
+ try {
288
+ svgText = dwg.dwg_to_svg(database);
289
+ } catch (error) {
290
+ throw new Error(`cannot export SVG for "${displayPath}": ${error.message}`);
291
+ }
292
+ const svgDisplay =
293
+ args.svg_output_path && args.svg_output_path.trim()
294
+ ? args.svg_output_path.trim()
295
+ : displayPath.replace(/\.dwg$/i, "") + ".dwg.svg";
296
+ const svgTarget = await ctx.fs.resolve(svgDisplay, resolveOptions);
297
+ let sandboxPolicy;
298
+ if (ctx.fs.sandboxMode !== undefined) {
299
+ const policyService = ctx.get("sandboxPolicy");
300
+ if (policyService) {
301
+ try {
302
+ sandboxPolicy = policyService.resolve({
303
+ ...(exec.agent ? { session: exec.agent.session } : {}),
304
+ });
305
+ } catch {}
306
+ }
307
+ }
308
+ const intent = await ctx.waterfall("fs/write-intent", svgTarget, exec, () => undefined);
309
+ let outcome;
310
+ try {
311
+ outcome = await ctx.fs.writeText(svgTarget, svgText, intent, exec.signal, sandboxPolicy);
312
+ } catch (error) {
313
+ throw new Error(
314
+ `cannot write SVG "${svgDisplay}": ${error.message}(可改用 svg_output_path 指向工作区内的路径)`
315
+ );
316
+ }
317
+ ctx.emit("fs/observed", svgTarget, { kind: "present", version: outcome.version }, exec);
318
+ svgPath = ctx.fs.processPath(svgTarget);
319
+ }
320
+
321
+ return toJson({
322
+ path: displayPath,
323
+ fileName: displayPath.split(/[\\/]/).pop(),
324
+ fileSizeBytes: info.size !== undefined ? info.size : bytes.byteLength,
325
+ versionType: version.type != null ? String(version.type) : "",
326
+ versionDescription: version.description != null ? String(version.description) : "",
327
+ codepage: typeof codepage === "number" ? codepage : -1,
328
+ codepageName: DwgCodePage[codepage] != null ? String(DwgCodePage[codepage]) : "CP_UNKNOWN",
329
+ header: headerSummary,
330
+ layerCount: layers.length,
331
+ layers,
332
+ blockCount: database.tables.BLOCK_RECORD.entries.length,
333
+ entityCount: database.entities.length,
334
+ entityTypeCounts,
335
+ unknownEntityCount: stats.unknownEntityCount || 0,
336
+ thumbnailPresent: !!database.thumbnailImage,
337
+ entities,
338
+ entitiesTruncated: !!args.entities && database.entities.length > limit,
339
+ svgPath,
340
+ });
341
+ } finally {
342
+ try {
343
+ dwg.dwg_free(dataPtr);
344
+ } catch {}
345
+ }
346
+ },
347
+ };
348
+ }
349
+
350
+ export const inject = ["tools", "fs", "workingDirectory"];
351
+
352
+ export function apply(ctx, config) {
353
+ const dispose = ctx.tools.register(buildReadDwgTool(ctx));
354
+ return () => dispose();
355
+ }
package/locale/en.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "DWG Reader",
4
+ "description": "Parses AutoCAD DWG drawings directly via libredwg-web (WASM): version, layers, blocks, entity stats/details, optional SVG preview export."
5
+ }
6
+ }
package/locale/zh.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "meta": {
3
+ "title": "DWG 读取器",
4
+ "description": "基于 libredwg-web(WASM)直接解析 AutoCAD DWG 图纸:版本、图层、块、实体统计与明细,可选导出 SVG 预览。"
5
+ }
6
+ }
package/package.json CHANGED
@@ -1,6 +1,34 @@
1
1
  {
2
2
  "name": "@bill_nee/dwg-reader",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "直接读取 AutoCAD DWG 图纸的 DSH 插件(基于 libredwg-web 0.8.2 WASM,GPL-3.0)。",
5
+ "license": "GPL-3.0-only",
6
+ "author": "MEB 工程造价项目助手 <meb@example.com>",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dwg-reader-plugin/dwg-reader"
10
+ },
11
+ "keywords": ["dwg", "dwg-reader", "autocad", "cad", "dsh-plugin", "libredwg", "wasm"],
12
+ "type": "module",
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
16
+ "exports": {
17
+ ".": "./lib/index.js",
18
+ "./locale/*.json": "./locale/*.json",
19
+ "./icon": "./icon.svg"
20
+ },
21
+ "files": [
22
+ "lib/index.js",
23
+ "vendor",
24
+ "cordis.patch.yml",
25
+ "locale/*.json",
26
+ "icon.svg",
27
+ "LICENSE"
28
+ ],
29
+ "dsh": {
30
+ "bundle": {
31
+ "patch": "./cordis.patch.yml"
32
+ }
33
+ }
34
+ }