@mlightcad/cad-simple-viewer-cli 1.7.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +143 -140
- package/dist-runner/assets/cad-html-plugin-CH5xALXb.js +1547 -0
- package/dist-runner/assets/cad-pdf-plugin-DkcMorOI.js +213 -0
- package/dist-runner/assets/{cad-svg-plugin-D7i6E3aJ.js → cad-svg-plugin-BJNA8aLS.js} +7 -7
- package/dist-runner/assets/index-BSoxUnC1.js +7324 -0
- package/dist-runner/index.html +12 -12
- package/dist-runner/viewer-runtime.iife.js +892 -236
- package/dist-runner/workers/libredwg-parser-worker.js +19 -19
- package/dist-runner/workers/mtext-renderer-worker.js +1908 -1765
- package/examples/batch-export-html-multi-preview.mjs +236 -0
- package/examples/batch-export-html.mjs +105 -105
- package/examples/batch-export-png.mjs +103 -103
- package/examples/create-drawing-dxf.scr +15 -15
- package/examples/create-drawing-png.scr +19 -19
- package/examples/create-shapes-dxf.scr +17 -17
- package/examples/export-dxf.scr +5 -5
- package/examples/export-html-multi-preview.scr +18 -0
- package/examples/export-html-multi.scr +13 -13
- package/examples/export-html.scr +12 -12
- package/examples/export-pdf.scr +9 -0
- package/examples/export-png.scr +9 -9
- package/examples/freeze-layer-png.scr +15 -15
- package/examples/index.json +114 -96
- package/package.json +9 -8
- package/dist-runner/assets/cad-html-plugin-Dw_UabVa.js +0 -1526
- package/dist-runner/assets/cad-pdf-plugin-BoBimdKx.js +0 -312
- package/dist-runner/assets/index-D6ZWapu2.js +0 -6993
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Recursively scan a directory for .dwg / .dxf files, export each to a
|
|
4
|
+
* multi-file ACEX zip + zoom-extents JPEG via export-html-multi-preview.scr,
|
|
5
|
+
* then arrange outputs in the demo-drawings package layout:
|
|
6
|
+
*
|
|
7
|
+
* <outputDir>/<folder>/
|
|
8
|
+
* drawing.acex.json
|
|
9
|
+
* chunks/
|
|
10
|
+
* preview.jpg
|
|
11
|
+
* drawing.dwg | drawing.dxf
|
|
12
|
+
*
|
|
13
|
+
* Folder names match demo-drawings: the path relative to <inputDir> without
|
|
14
|
+
* extension, with path separators turned into underscores. Same-stem
|
|
15
|
+
* `.dwg`/`.dxf` pairs get a `_dwg` / `_dxf` suffix so they do not collide.
|
|
16
|
+
*
|
|
17
|
+
* Usage (from packages/cad-simple-viewer-cli after build):
|
|
18
|
+
* node examples/batch-export-html-multi-preview.mjs <inputDir> <outputDir>
|
|
19
|
+
*/
|
|
20
|
+
import { spawn, spawnSync } from 'node:child_process'
|
|
21
|
+
import { existsSync } from 'node:fs'
|
|
22
|
+
import {
|
|
23
|
+
copyFile,
|
|
24
|
+
mkdir,
|
|
25
|
+
mkdtemp,
|
|
26
|
+
readdir,
|
|
27
|
+
rename,
|
|
28
|
+
rm
|
|
29
|
+
} from 'node:fs/promises'
|
|
30
|
+
import os from 'node:os'
|
|
31
|
+
import path from 'node:path'
|
|
32
|
+
import { fileURLToPath } from 'node:url'
|
|
33
|
+
|
|
34
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
35
|
+
const packageRoot = path.resolve(__dirname, '..')
|
|
36
|
+
const cliJs = path.join(packageRoot, 'dist', 'cli.js')
|
|
37
|
+
const scriptPath = path.join(__dirname, 'export-html-multi-preview.scr')
|
|
38
|
+
|
|
39
|
+
const DRAWING_EXT = new Set(['.dwg', '.dxf'])
|
|
40
|
+
|
|
41
|
+
/** True when `child` is `parent` or a path under it. */
|
|
42
|
+
function isPathInside(parent, child) {
|
|
43
|
+
const rel = path.relative(parent, child)
|
|
44
|
+
return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel))
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function collectDrawings(dir, out = [], excludeDir) {
|
|
48
|
+
if (excludeDir && isPathInside(excludeDir, dir)) {
|
|
49
|
+
return out
|
|
50
|
+
}
|
|
51
|
+
const entries = await readdir(dir, { withFileTypes: true })
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
const full = path.join(dir, entry.name)
|
|
54
|
+
if (entry.isDirectory()) {
|
|
55
|
+
await collectDrawings(full, out, excludeDir)
|
|
56
|
+
} else if (DRAWING_EXT.has(path.extname(entry.name).toLowerCase())) {
|
|
57
|
+
if (!(excludeDir && isPathInside(excludeDir, full))) {
|
|
58
|
+
out.push(full)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return out
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* demo-drawings-style folder name from a path relative to inputDir.
|
|
67
|
+
* `used` tracks claimed names so same-stem DWG/DXF pairs stay unique.
|
|
68
|
+
*/
|
|
69
|
+
function drawingFolderName(inputDir, drawingPath, used) {
|
|
70
|
+
const rel = path.relative(inputDir, drawingPath)
|
|
71
|
+
const ext = path.extname(rel).toLowerCase()
|
|
72
|
+
const withoutExt = ext ? rel.slice(0, -ext.length) : rel
|
|
73
|
+
const base = withoutExt
|
|
74
|
+
.split(/[/\\]/)
|
|
75
|
+
.filter(Boolean)
|
|
76
|
+
.join('_')
|
|
77
|
+
.replace(/[^\p{L}\p{N}._-]+/gu, '_')
|
|
78
|
+
const extTag = ext.replace(/^\./, '') || 'bin'
|
|
79
|
+
|
|
80
|
+
let name = base
|
|
81
|
+
if (used.has(name)) {
|
|
82
|
+
name = `${base}_${extTag}`
|
|
83
|
+
}
|
|
84
|
+
let n = 2
|
|
85
|
+
while (used.has(name)) {
|
|
86
|
+
name = `${base}_${extTag}_${n++}`
|
|
87
|
+
}
|
|
88
|
+
used.add(name)
|
|
89
|
+
return name
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function runCli(input, outputDir) {
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
const child = spawn(
|
|
95
|
+
process.execPath,
|
|
96
|
+
[
|
|
97
|
+
cliJs,
|
|
98
|
+
'-i',
|
|
99
|
+
input,
|
|
100
|
+
'-s',
|
|
101
|
+
scriptPath,
|
|
102
|
+
'-o',
|
|
103
|
+
outputDir,
|
|
104
|
+
'--mode',
|
|
105
|
+
'read'
|
|
106
|
+
],
|
|
107
|
+
{ stdio: 'inherit' }
|
|
108
|
+
)
|
|
109
|
+
child.on('error', reject)
|
|
110
|
+
child.on('exit', code => {
|
|
111
|
+
if (code === 0) resolve()
|
|
112
|
+
else
|
|
113
|
+
reject(
|
|
114
|
+
new Error(
|
|
115
|
+
`cad-simple-viewer-cli exited with code ${code} for ${input}`
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function unzipWithTar(zipPath, destDir) {
|
|
123
|
+
const result = spawnSync(
|
|
124
|
+
'tar',
|
|
125
|
+
['-xf', zipPath, '-C', destDir],
|
|
126
|
+
{ encoding: 'utf8' }
|
|
127
|
+
)
|
|
128
|
+
if (result.status !== 0) {
|
|
129
|
+
throw new Error(
|
|
130
|
+
`Failed to unzip ${zipPath}: ${result.stderr || result.stdout || 'tar error'}`
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function packageDrawing(workDir, targetDir, sourceDrawing) {
|
|
136
|
+
const entries = await readdir(workDir)
|
|
137
|
+
const zipName = entries.find(name => name.toLowerCase().endsWith('.zip'))
|
|
138
|
+
const jpegName = entries.find(name => {
|
|
139
|
+
const lower = name.toLowerCase()
|
|
140
|
+
return lower.endsWith('.jpg') || lower.endsWith('.jpeg')
|
|
141
|
+
})
|
|
142
|
+
if (!zipName) {
|
|
143
|
+
throw new Error(`No .zip produced in ${workDir}`)
|
|
144
|
+
}
|
|
145
|
+
if (!jpegName) {
|
|
146
|
+
throw new Error(`No .jpg preview produced in ${workDir}`)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Stage under the same parent as targetDir so rename stays on one volume.
|
|
150
|
+
const stageDir = await mkdtemp(
|
|
151
|
+
path.join(path.dirname(targetDir), '.cad-cli-pack-')
|
|
152
|
+
)
|
|
153
|
+
try {
|
|
154
|
+
unzipWithTar(path.join(workDir, zipName), stageDir)
|
|
155
|
+
|
|
156
|
+
await copyFile(
|
|
157
|
+
path.join(workDir, jpegName),
|
|
158
|
+
path.join(stageDir, 'preview.jpg')
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
const ext = path.extname(sourceDrawing).toLowerCase()
|
|
162
|
+
const destName = ext === '.dxf' ? 'drawing.dxf' : 'drawing.dwg'
|
|
163
|
+
await copyFile(sourceDrawing, path.join(stageDir, destName))
|
|
164
|
+
|
|
165
|
+
await rm(targetDir, { recursive: true, force: true })
|
|
166
|
+
await rename(stageDir, targetDir)
|
|
167
|
+
} catch (error) {
|
|
168
|
+
await rm(stageDir, { recursive: true, force: true })
|
|
169
|
+
throw error
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async function main() {
|
|
174
|
+
const inputDir = path.resolve(process.argv[2] ?? '')
|
|
175
|
+
const outputDir = path.resolve(process.argv[3] ?? '')
|
|
176
|
+
|
|
177
|
+
if (!process.argv[2] || !process.argv[3] || !existsSync(inputDir)) {
|
|
178
|
+
console.error(
|
|
179
|
+
'Usage: node examples/batch-export-html-multi-preview.mjs <inputDir> <outputDir>'
|
|
180
|
+
)
|
|
181
|
+
process.exitCode = 1
|
|
182
|
+
return
|
|
183
|
+
}
|
|
184
|
+
if (!existsSync(cliJs)) {
|
|
185
|
+
console.error(
|
|
186
|
+
'CLI not built. Run: pnpm --filter @mlightcad/cad-simple-viewer-cli build'
|
|
187
|
+
)
|
|
188
|
+
process.exitCode = 1
|
|
189
|
+
return
|
|
190
|
+
}
|
|
191
|
+
if (!existsSync(scriptPath)) {
|
|
192
|
+
console.error(`Missing script: ${scriptPath}`)
|
|
193
|
+
process.exitCode = 1
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
await mkdir(outputDir, { recursive: true })
|
|
198
|
+
// Skip anything already under outputDir so a nested out/ does not re-scan
|
|
199
|
+
// packaged drawing.dwg / drawing.dxf copies on later runs.
|
|
200
|
+
const drawings = await collectDrawings(inputDir, [], outputDir)
|
|
201
|
+
if (!drawings.length) {
|
|
202
|
+
console.error(`No .dwg/.dxf files found under ${inputDir}`)
|
|
203
|
+
process.exitCode = 1
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
console.log(
|
|
208
|
+
`Found ${drawings.length} drawing(s). Output (demo-drawings layout): ${outputDir}`
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
const usedFolders = new Set()
|
|
212
|
+
let failed = 0
|
|
213
|
+
|
|
214
|
+
for (const drawing of drawings) {
|
|
215
|
+
const folder = drawingFolderName(inputDir, drawing, usedFolders)
|
|
216
|
+
const targetDir = path.join(outputDir, folder)
|
|
217
|
+
console.log(`\n=== ${drawing} → ${folder}/ ===`)
|
|
218
|
+
|
|
219
|
+
const workDir = await mkdtemp(path.join(os.tmpdir(), 'cad-cli-demo-'))
|
|
220
|
+
try {
|
|
221
|
+
await runCli(drawing, workDir)
|
|
222
|
+
await packageDrawing(workDir, targetDir, drawing)
|
|
223
|
+
console.log(`Packaged ${targetDir}`)
|
|
224
|
+
} catch (error) {
|
|
225
|
+
failed++
|
|
226
|
+
console.error(error instanceof Error ? error.message : String(error))
|
|
227
|
+
} finally {
|
|
228
|
+
await rm(workDir, { recursive: true, force: true })
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
console.log(`\nDone. success=${drawings.length - failed} failed=${failed}`)
|
|
233
|
+
if (failed) process.exitCode = 1
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
await main()
|
|
@@ -1,105 +1,105 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Recursively scan a directory for .dwg / .dxf files and export each to HTML
|
|
4
|
-
* via cad-simple-viewer-cli + export-html.scr.
|
|
5
|
-
*
|
|
6
|
-
* Usage (from packages/cad-simple-viewer-cli after build):
|
|
7
|
-
* node examples/batch-export-html.mjs <inputDir> [outputDir]
|
|
8
|
-
*/
|
|
9
|
-
import { spawn } from 'node:child_process'
|
|
10
|
-
import { existsSync } from 'node:fs'
|
|
11
|
-
import { mkdir, readdir } from 'node:fs/promises'
|
|
12
|
-
import path from 'node:path'
|
|
13
|
-
import { fileURLToPath } from 'node:url'
|
|
14
|
-
|
|
15
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
16
|
-
const packageRoot = path.resolve(__dirname, '..')
|
|
17
|
-
const cliJs = path.join(packageRoot, 'dist', 'cli.js')
|
|
18
|
-
const scriptPath = path.join(__dirname, 'export-html.scr')
|
|
19
|
-
|
|
20
|
-
const DRAWING_EXT = new Set(['.dwg', '.dxf'])
|
|
21
|
-
|
|
22
|
-
async function collectDrawings(dir, out = []) {
|
|
23
|
-
const entries = await readdir(dir, { withFileTypes: true })
|
|
24
|
-
for (const entry of entries) {
|
|
25
|
-
const full = path.join(dir, entry.name)
|
|
26
|
-
if (entry.isDirectory()) {
|
|
27
|
-
await collectDrawings(full, out)
|
|
28
|
-
} else if (DRAWING_EXT.has(path.extname(entry.name).toLowerCase())) {
|
|
29
|
-
out.push(full)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return out
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function runCli(input, outputDir) {
|
|
36
|
-
return new Promise((resolve, reject) => {
|
|
37
|
-
const child = spawn(
|
|
38
|
-
process.execPath,
|
|
39
|
-
[
|
|
40
|
-
cliJs,
|
|
41
|
-
'-i',
|
|
42
|
-
input,
|
|
43
|
-
'-s',
|
|
44
|
-
scriptPath,
|
|
45
|
-
'-o',
|
|
46
|
-
outputDir,
|
|
47
|
-
'--mode',
|
|
48
|
-
'read'
|
|
49
|
-
],
|
|
50
|
-
{ stdio: 'inherit' }
|
|
51
|
-
)
|
|
52
|
-
child.on('error', reject)
|
|
53
|
-
child.on('exit', code => {
|
|
54
|
-
if (code === 0) resolve()
|
|
55
|
-
else reject(new Error(`cad-simple-viewer-cli exited with code ${code} for ${input}`))
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function main() {
|
|
61
|
-
const inputDir = path.resolve(process.argv[2] ?? '')
|
|
62
|
-
const outputDir = path.resolve(
|
|
63
|
-
process.argv[3] ?? path.join(inputDir, 'html-out')
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
if (!process.argv[2] || !existsSync(inputDir)) {
|
|
67
|
-
console.error(
|
|
68
|
-
'Usage: node examples/batch-export-html.mjs <inputDir> [outputDir]'
|
|
69
|
-
)
|
|
70
|
-
process.exitCode = 1
|
|
71
|
-
return
|
|
72
|
-
}
|
|
73
|
-
if (!existsSync(cliJs)) {
|
|
74
|
-
console.error(
|
|
75
|
-
'CLI not built. Run: pnpm --filter @mlightcad/cad-simple-viewer-cli build'
|
|
76
|
-
)
|
|
77
|
-
process.exitCode = 1
|
|
78
|
-
return
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
await mkdir(outputDir, { recursive: true })
|
|
82
|
-
const drawings = await collectDrawings(inputDir)
|
|
83
|
-
if (!drawings.length) {
|
|
84
|
-
console.error(`No .dwg/.dxf files found under ${inputDir}`)
|
|
85
|
-
process.exitCode = 1
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
console.log(`Found ${drawings.length} drawing(s). Output: ${outputDir}`)
|
|
90
|
-
let failed = 0
|
|
91
|
-
for (const drawing of drawings) {
|
|
92
|
-
console.log(`\n=== ${drawing} ===`)
|
|
93
|
-
try {
|
|
94
|
-
await runCli(drawing, outputDir)
|
|
95
|
-
} catch (error) {
|
|
96
|
-
failed++
|
|
97
|
-
console.error(error instanceof Error ? error.message : String(error))
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
console.log(`\nDone. success=${drawings.length - failed} failed=${failed}`)
|
|
102
|
-
if (failed) process.exitCode = 1
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
await main()
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Recursively scan a directory for .dwg / .dxf files and export each to HTML
|
|
4
|
+
* via cad-simple-viewer-cli + export-html.scr.
|
|
5
|
+
*
|
|
6
|
+
* Usage (from packages/cad-simple-viewer-cli after build):
|
|
7
|
+
* node examples/batch-export-html.mjs <inputDir> [outputDir]
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from 'node:child_process'
|
|
10
|
+
import { existsSync } from 'node:fs'
|
|
11
|
+
import { mkdir, readdir } from 'node:fs/promises'
|
|
12
|
+
import path from 'node:path'
|
|
13
|
+
import { fileURLToPath } from 'node:url'
|
|
14
|
+
|
|
15
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
16
|
+
const packageRoot = path.resolve(__dirname, '..')
|
|
17
|
+
const cliJs = path.join(packageRoot, 'dist', 'cli.js')
|
|
18
|
+
const scriptPath = path.join(__dirname, 'export-html.scr')
|
|
19
|
+
|
|
20
|
+
const DRAWING_EXT = new Set(['.dwg', '.dxf'])
|
|
21
|
+
|
|
22
|
+
async function collectDrawings(dir, out = []) {
|
|
23
|
+
const entries = await readdir(dir, { withFileTypes: true })
|
|
24
|
+
for (const entry of entries) {
|
|
25
|
+
const full = path.join(dir, entry.name)
|
|
26
|
+
if (entry.isDirectory()) {
|
|
27
|
+
await collectDrawings(full, out)
|
|
28
|
+
} else if (DRAWING_EXT.has(path.extname(entry.name).toLowerCase())) {
|
|
29
|
+
out.push(full)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return out
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function runCli(input, outputDir) {
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
const child = spawn(
|
|
38
|
+
process.execPath,
|
|
39
|
+
[
|
|
40
|
+
cliJs,
|
|
41
|
+
'-i',
|
|
42
|
+
input,
|
|
43
|
+
'-s',
|
|
44
|
+
scriptPath,
|
|
45
|
+
'-o',
|
|
46
|
+
outputDir,
|
|
47
|
+
'--mode',
|
|
48
|
+
'read'
|
|
49
|
+
],
|
|
50
|
+
{ stdio: 'inherit' }
|
|
51
|
+
)
|
|
52
|
+
child.on('error', reject)
|
|
53
|
+
child.on('exit', code => {
|
|
54
|
+
if (code === 0) resolve()
|
|
55
|
+
else reject(new Error(`cad-simple-viewer-cli exited with code ${code} for ${input}`))
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function main() {
|
|
61
|
+
const inputDir = path.resolve(process.argv[2] ?? '')
|
|
62
|
+
const outputDir = path.resolve(
|
|
63
|
+
process.argv[3] ?? path.join(inputDir, 'html-out')
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if (!process.argv[2] || !existsSync(inputDir)) {
|
|
67
|
+
console.error(
|
|
68
|
+
'Usage: node examples/batch-export-html.mjs <inputDir> [outputDir]'
|
|
69
|
+
)
|
|
70
|
+
process.exitCode = 1
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
if (!existsSync(cliJs)) {
|
|
74
|
+
console.error(
|
|
75
|
+
'CLI not built. Run: pnpm --filter @mlightcad/cad-simple-viewer-cli build'
|
|
76
|
+
)
|
|
77
|
+
process.exitCode = 1
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
await mkdir(outputDir, { recursive: true })
|
|
82
|
+
const drawings = await collectDrawings(inputDir)
|
|
83
|
+
if (!drawings.length) {
|
|
84
|
+
console.error(`No .dwg/.dxf files found under ${inputDir}`)
|
|
85
|
+
process.exitCode = 1
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log(`Found ${drawings.length} drawing(s). Output: ${outputDir}`)
|
|
90
|
+
let failed = 0
|
|
91
|
+
for (const drawing of drawings) {
|
|
92
|
+
console.log(`\n=== ${drawing} ===`)
|
|
93
|
+
try {
|
|
94
|
+
await runCli(drawing, outputDir)
|
|
95
|
+
} catch (error) {
|
|
96
|
+
failed++
|
|
97
|
+
console.error(error instanceof Error ? error.message : String(error))
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
console.log(`\nDone. success=${drawings.length - failed} failed=${failed}`)
|
|
102
|
+
if (failed) process.exitCode = 1
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
await main()
|
|
@@ -1,103 +1,103 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Recursively scan a directory for .dwg / .dxf files and export each to PNG
|
|
4
|
-
* via cad-simple-viewer-cli + export-png.scr.
|
|
5
|
-
*
|
|
6
|
-
* Usage (from packages/cad-simple-viewer-cli after build):
|
|
7
|
-
* node examples/batch-export-png.mjs <inputDir> [outputDir]
|
|
8
|
-
*/
|
|
9
|
-
import { spawn } from 'node:child_process'
|
|
10
|
-
import { existsSync } from 'node:fs'
|
|
11
|
-
import { mkdir, readdir } from 'node:fs/promises'
|
|
12
|
-
import path from 'node:path'
|
|
13
|
-
import { fileURLToPath } from 'node:url'
|
|
14
|
-
|
|
15
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
16
|
-
const packageRoot = path.resolve(__dirname, '..')
|
|
17
|
-
const cliJs = path.join(packageRoot, 'dist', 'cli.js')
|
|
18
|
-
const scriptPath = path.join(__dirname, 'export-png.scr')
|
|
19
|
-
|
|
20
|
-
const DRAWING_EXT = new Set(['.dwg', '.dxf'])
|
|
21
|
-
|
|
22
|
-
async function collectDrawings(dir, out = []) {
|
|
23
|
-
const entries = await readdir(dir, { withFileTypes: true })
|
|
24
|
-
for (const entry of entries) {
|
|
25
|
-
const full = path.join(dir, entry.name)
|
|
26
|
-
if (entry.isDirectory()) {
|
|
27
|
-
await collectDrawings(full, out)
|
|
28
|
-
} else if (DRAWING_EXT.has(path.extname(entry.name).toLowerCase())) {
|
|
29
|
-
out.push(full)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return out
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function runCli(input, outputDir) {
|
|
36
|
-
return new Promise((resolve, reject) => {
|
|
37
|
-
const child = spawn(
|
|
38
|
-
process.execPath,
|
|
39
|
-
[
|
|
40
|
-
cliJs,
|
|
41
|
-
'-i',
|
|
42
|
-
input,
|
|
43
|
-
'-s',
|
|
44
|
-
scriptPath,
|
|
45
|
-
'-o',
|
|
46
|
-
outputDir,
|
|
47
|
-
'--mode',
|
|
48
|
-
'read'
|
|
49
|
-
],
|
|
50
|
-
{ stdio: 'inherit' }
|
|
51
|
-
)
|
|
52
|
-
child.on('error', reject)
|
|
53
|
-
child.on('exit', code => {
|
|
54
|
-
if (code === 0) resolve()
|
|
55
|
-
else reject(new Error(`cad-simple-viewer-cli exited with code ${code} for ${input}`))
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function main() {
|
|
61
|
-
const inputDir = path.resolve(process.argv[2] ?? '')
|
|
62
|
-
const outputDir = path.resolve(process.argv[3] ?? path.join(inputDir, 'png-out'))
|
|
63
|
-
|
|
64
|
-
if (!process.argv[2] || !existsSync(inputDir)) {
|
|
65
|
-
console.error(
|
|
66
|
-
'Usage: node examples/batch-export-png.mjs <inputDir> [outputDir]'
|
|
67
|
-
)
|
|
68
|
-
process.exitCode = 1
|
|
69
|
-
return
|
|
70
|
-
}
|
|
71
|
-
if (!existsSync(cliJs)) {
|
|
72
|
-
console.error(
|
|
73
|
-
'CLI not built. Run: pnpm --filter @mlightcad/cad-simple-viewer-cli build'
|
|
74
|
-
)
|
|
75
|
-
process.exitCode = 1
|
|
76
|
-
return
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
await mkdir(outputDir, { recursive: true })
|
|
80
|
-
const drawings = await collectDrawings(inputDir)
|
|
81
|
-
if (!drawings.length) {
|
|
82
|
-
console.error(`No .dwg/.dxf files found under ${inputDir}`)
|
|
83
|
-
process.exitCode = 1
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
console.log(`Found ${drawings.length} drawing(s). Output: ${outputDir}`)
|
|
88
|
-
let failed = 0
|
|
89
|
-
for (const drawing of drawings) {
|
|
90
|
-
console.log(`\n=== ${drawing} ===`)
|
|
91
|
-
try {
|
|
92
|
-
await runCli(drawing, outputDir)
|
|
93
|
-
} catch (error) {
|
|
94
|
-
failed++
|
|
95
|
-
console.error(error instanceof Error ? error.message : String(error))
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
console.log(`\nDone. success=${drawings.length - failed} failed=${failed}`)
|
|
100
|
-
if (failed) process.exitCode = 1
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
await main()
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Recursively scan a directory for .dwg / .dxf files and export each to PNG
|
|
4
|
+
* via cad-simple-viewer-cli + export-png.scr.
|
|
5
|
+
*
|
|
6
|
+
* Usage (from packages/cad-simple-viewer-cli after build):
|
|
7
|
+
* node examples/batch-export-png.mjs <inputDir> [outputDir]
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from 'node:child_process'
|
|
10
|
+
import { existsSync } from 'node:fs'
|
|
11
|
+
import { mkdir, readdir } from 'node:fs/promises'
|
|
12
|
+
import path from 'node:path'
|
|
13
|
+
import { fileURLToPath } from 'node:url'
|
|
14
|
+
|
|
15
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
16
|
+
const packageRoot = path.resolve(__dirname, '..')
|
|
17
|
+
const cliJs = path.join(packageRoot, 'dist', 'cli.js')
|
|
18
|
+
const scriptPath = path.join(__dirname, 'export-png.scr')
|
|
19
|
+
|
|
20
|
+
const DRAWING_EXT = new Set(['.dwg', '.dxf'])
|
|
21
|
+
|
|
22
|
+
async function collectDrawings(dir, out = []) {
|
|
23
|
+
const entries = await readdir(dir, { withFileTypes: true })
|
|
24
|
+
for (const entry of entries) {
|
|
25
|
+
const full = path.join(dir, entry.name)
|
|
26
|
+
if (entry.isDirectory()) {
|
|
27
|
+
await collectDrawings(full, out)
|
|
28
|
+
} else if (DRAWING_EXT.has(path.extname(entry.name).toLowerCase())) {
|
|
29
|
+
out.push(full)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return out
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function runCli(input, outputDir) {
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
const child = spawn(
|
|
38
|
+
process.execPath,
|
|
39
|
+
[
|
|
40
|
+
cliJs,
|
|
41
|
+
'-i',
|
|
42
|
+
input,
|
|
43
|
+
'-s',
|
|
44
|
+
scriptPath,
|
|
45
|
+
'-o',
|
|
46
|
+
outputDir,
|
|
47
|
+
'--mode',
|
|
48
|
+
'read'
|
|
49
|
+
],
|
|
50
|
+
{ stdio: 'inherit' }
|
|
51
|
+
)
|
|
52
|
+
child.on('error', reject)
|
|
53
|
+
child.on('exit', code => {
|
|
54
|
+
if (code === 0) resolve()
|
|
55
|
+
else reject(new Error(`cad-simple-viewer-cli exited with code ${code} for ${input}`))
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function main() {
|
|
61
|
+
const inputDir = path.resolve(process.argv[2] ?? '')
|
|
62
|
+
const outputDir = path.resolve(process.argv[3] ?? path.join(inputDir, 'png-out'))
|
|
63
|
+
|
|
64
|
+
if (!process.argv[2] || !existsSync(inputDir)) {
|
|
65
|
+
console.error(
|
|
66
|
+
'Usage: node examples/batch-export-png.mjs <inputDir> [outputDir]'
|
|
67
|
+
)
|
|
68
|
+
process.exitCode = 1
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
if (!existsSync(cliJs)) {
|
|
72
|
+
console.error(
|
|
73
|
+
'CLI not built. Run: pnpm --filter @mlightcad/cad-simple-viewer-cli build'
|
|
74
|
+
)
|
|
75
|
+
process.exitCode = 1
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await mkdir(outputDir, { recursive: true })
|
|
80
|
+
const drawings = await collectDrawings(inputDir)
|
|
81
|
+
if (!drawings.length) {
|
|
82
|
+
console.error(`No .dwg/.dxf files found under ${inputDir}`)
|
|
83
|
+
process.exitCode = 1
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log(`Found ${drawings.length} drawing(s). Output: ${outputDir}`)
|
|
88
|
+
let failed = 0
|
|
89
|
+
for (const drawing of drawings) {
|
|
90
|
+
console.log(`\n=== ${drawing} ===`)
|
|
91
|
+
try {
|
|
92
|
+
await runCli(drawing, outputDir)
|
|
93
|
+
} catch (error) {
|
|
94
|
+
failed++
|
|
95
|
+
console.error(error instanceof Error ? error.message : String(error))
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log(`\nDone. success=${drawings.length - failed} failed=${failed}`)
|
|
100
|
+
if (failed) process.exitCode = 1
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
await main()
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
; Create a new ISO drawing, draw a closed rectangle with LINE, then export DXF.
|
|
2
|
-
; No -i needed (CLI starts from a blank template; qnew refreshes from ISO).
|
|
3
|
-
; Usage:
|
|
4
|
-
; cad-simple-viewer-cli -s examples/create-drawing-dxf.scr -o ./out --mode write
|
|
5
|
-
qnew
|
|
6
|
-
line
|
|
7
|
-
0,0
|
|
8
|
-
100,0
|
|
9
|
-
100,60
|
|
10
|
-
0,60
|
|
11
|
-
c
|
|
12
|
-
zoom
|
|
13
|
-
e
|
|
14
|
-
cdxf
|
|
15
|
-
quit
|
|
1
|
+
; Create a new ISO drawing, draw a closed rectangle with LINE, then export DXF.
|
|
2
|
+
; No -i needed (CLI starts from a blank template; qnew refreshes from ISO).
|
|
3
|
+
; Usage:
|
|
4
|
+
; cad-simple-viewer-cli -s examples/create-drawing-dxf.scr -o ./out --mode write
|
|
5
|
+
qnew
|
|
6
|
+
line
|
|
7
|
+
0,0
|
|
8
|
+
100,0
|
|
9
|
+
100,60
|
|
10
|
+
0,60
|
|
11
|
+
c
|
|
12
|
+
zoom
|
|
13
|
+
e
|
|
14
|
+
cdxf
|
|
15
|
+
quit
|