node-plantuml-2 1.1.1 → 1.1.3

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.
@@ -224,8 +224,16 @@ function joinOptions (argv, options) {
224
224
  }
225
225
 
226
226
  if (options.dot) {
227
+ // Ensure dot path is absolute - PlantUML Java process needs absolute path
228
+ var absoluteDotPath = path.resolve(options.dot)
229
+ // Normalize path separators
230
+ if (process.platform === 'win32') {
231
+ absoluteDotPath = absoluteDotPath.replace(/\//g, '\\')
232
+ } else {
233
+ absoluteDotPath = absoluteDotPath.replace(/\\/g, '/')
234
+ }
227
235
  argv.push(DOT)
228
- argv.push(options.dot)
236
+ argv.push(absoluteDotPath)
229
237
  }
230
238
 
231
239
  if (options.charset) {
@@ -92,10 +92,12 @@ function execWithSpawn (argv, cwd, options, cb) {
92
92
 
93
93
  // Check if we're using bundled Graphviz and need to set library path
94
94
  var dotPath = null
95
+ var dotPathIndex = -1
95
96
  // Extract dot path from argv if present
96
97
  for (var i = 0; i < argv.length; i++) {
97
98
  if (argv[i] === '-graphvizdot' && i + 1 < argv.length) {
98
99
  dotPath = argv[i + 1]
100
+ dotPathIndex = i + 1
99
101
  break
100
102
  }
101
103
  }
@@ -105,17 +107,55 @@ function execWithSpawn (argv, cwd, options, cb) {
105
107
  dotPath = dotResolver.resolveDotExecutable({ dotPath: null })
106
108
  }
107
109
 
110
+ // CRITICAL FIX: Ensure dot path is absolute and properly formatted
111
+ // PlantUML Java process needs absolute path to launch Graphviz subprocess
112
+ if (dotPath) {
113
+ // Convert to absolute path
114
+ var absoluteDotPath = path.resolve(dotPath)
115
+
116
+ // Normalize path separators for the platform
117
+ if (process.platform === 'win32') {
118
+ // Windows: Use backslashes and ensure .exe extension
119
+ absoluteDotPath = absoluteDotPath.replace(/\//g, '\\')
120
+ if (!absoluteDotPath.toLowerCase().endsWith('.exe')) {
121
+ // If path doesn't end with .exe, check if it's a directory and add dot.exe
122
+ var fs = require('fs')
123
+ try {
124
+ var stat = fs.statSync(absoluteDotPath)
125
+ if (stat.isDirectory()) {
126
+ absoluteDotPath = path.join(absoluteDotPath, 'dot.exe')
127
+ }
128
+ } catch (e) {
129
+ // Ignore errors
130
+ }
131
+ }
132
+ } else {
133
+ // Unix: Use forward slashes
134
+ absoluteDotPath = absoluteDotPath.replace(/\\/g, '/')
135
+ }
136
+
137
+ // Update argv with absolute path if it was found in argv
138
+ if (dotPathIndex >= 0) {
139
+ argv[dotPathIndex] = absoluteDotPath
140
+ }
141
+
142
+ // Use absolute path for environment variable setup
143
+ dotPath = absoluteDotPath
144
+ }
145
+
108
146
  // Get library path for bundled Graphviz
109
147
  var libPath = dotResolver.getBundledGraphvizLibPath(dotPath)
110
148
  var platform = require('os').platform()
111
149
 
112
- // Only create new env object if we need to modify it
113
- var envModified = false
114
- var env = null
150
+ // Always create env object to ensure environment variables are properly set
151
+ // This is critical for Java subprocess to inherit correct environment
152
+ var env = Object.assign({}, process.env)
153
+ var envModified = true
115
154
 
116
155
  if (libPath) {
117
- env = Object.assign({}, process.env)
118
- envModified = true
156
+ // Ensure libPath is absolute
157
+ libPath = path.resolve(libPath)
158
+
119
159
  if (platform === 'linux') {
120
160
  // Set LD_LIBRARY_PATH for Linux
121
161
  var existingLibPath = env.LD_LIBRARY_PATH || ''
@@ -130,12 +170,10 @@ function execWithSpawn (argv, cwd, options, cb) {
130
170
  // For Windows, add Graphviz bin directory to PATH
131
171
  // This is needed for both bundled and system-installed Graphviz to find DLLs
132
172
  if (platform === 'win32' && dotPath) {
133
- if (!env) {
134
- env = Object.assign({}, process.env)
135
- envModified = true
136
- }
137
-
138
173
  var binDir = path.dirname(dotPath)
174
+ // Normalize to Windows path format
175
+ binDir = binDir.replace(/\//g, '\\')
176
+
139
177
  // On Windows, PATH might be Path (case-insensitive but Node.js preserves case)
140
178
  var pathKey = 'PATH'
141
179
  for (var key in process.env) {
@@ -147,14 +185,11 @@ function execWithSpawn (argv, cwd, options, cb) {
147
185
 
148
186
  var existingPath = env[pathKey] || env.PATH || ''
149
187
 
150
- // Normalize binDir to Windows path format
151
- binDir = binDir.replace(/\//g, '\\')
152
-
153
188
  // Check if bin directory is already in PATH
154
189
  var pathEntries = existingPath.split(';')
155
190
  var alreadyInPath = false
156
- for (var i = 0; i < pathEntries.length; i++) {
157
- var normalizedEntry = pathEntries[i].replace(/\//g, '\\').toLowerCase().trim()
191
+ for (var j = 0; j < pathEntries.length; j++) {
192
+ var normalizedEntry = pathEntries[j].replace(/\//g, '\\').toLowerCase().trim()
158
193
  if (normalizedEntry && normalizedEntry === binDir.toLowerCase()) {
159
194
  alreadyInPath = true
160
195
  break
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-plantuml-2",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "plantumlVersion": "1.2026.1",
5
5
  "description": "Node.js PlantUML renderer with Java backend. Multiple output formats (PNG, SVG, EPS, ASCII, Unicode) with full UTF-8 support",
6
6
  "main": "index.js",
@@ -26,13 +26,13 @@
26
26
  "plantuml-encoder": "^1.2.5"
27
27
  },
28
28
  "optionalDependencies": {
29
- "@node-plantuml-2/jre-win32-x64": "^1.1.1",
30
- "@node-plantuml-2/jre-darwin-arm64": "^1.1.1",
31
- "@node-plantuml-2/jre-linux-x64": "^1.1.1",
32
- "@node-plantuml-2/graphviz-win32-x64": "^1.1.1",
33
- "@node-plantuml-2/graphviz-darwin-arm64": "^1.1.1",
34
- "@node-plantuml-2/graphviz-darwin-x64": "^1.1.1",
35
- "@node-plantuml-2/graphviz-linux-x64": "^1.1.1"
29
+ "@node-plantuml-2/jre-win32-x64": "^1.1.3",
30
+ "@node-plantuml-2/jre-darwin-arm64": "^1.1.3",
31
+ "@node-plantuml-2/jre-linux-x64": "^1.1.3",
32
+ "@node-plantuml-2/graphviz-win32-x64": "^1.1.3",
33
+ "@node-plantuml-2/graphviz-darwin-arm64": "^1.1.3",
34
+ "@node-plantuml-2/graphviz-darwin-x64": "^1.1.3",
35
+ "@node-plantuml-2/graphviz-linux-x64": "^1.1.3"
36
36
  },
37
37
  "devDependencies": {
38
38
  "chai": "^4.x",
@@ -48,6 +48,7 @@
48
48
  "nail/plantumlnail.jar",
49
49
  "scripts/download.js",
50
50
  "scripts/get-vizjs.js",
51
+ "scripts/install-graphviz.js",
51
52
  "README.md"
52
53
  ],
53
54
  "scripts": {
@@ -0,0 +1,335 @@
1
+ #!/usr/bin/env node
2
+ 'use strict'
3
+
4
+ /**
5
+ * Cross-platform Graphviz installation script
6
+ * Attempts to automatically install Graphviz on Windows, Linux, and macOS
7
+ */
8
+
9
+ var os = require('os')
10
+ var childProcess = require('child_process')
11
+ var dotResolver = require('../lib/dot-resolver')
12
+
13
+ var platform = os.platform()
14
+ var isWindows = platform === 'win32'
15
+ var isMac = platform === 'darwin'
16
+ var isLinux = platform === 'linux'
17
+
18
+ /**
19
+ * Check if a command exists
20
+ */
21
+ function commandExists (command) {
22
+ try {
23
+ if (isWindows) {
24
+ childProcess.execSync('where ' + command + ' >nul 2>&1', { stdio: 'ignore' })
25
+ } else {
26
+ childProcess.execSync('which ' + command + ' > /dev/null 2>&1', { stdio: 'ignore' })
27
+ }
28
+ return true
29
+ } catch (e) {
30
+ return false
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Execute command and return result
36
+ */
37
+ function execCommand (command, args, options) {
38
+ return new Promise(function (resolve, reject) {
39
+ var child = childProcess.spawn(command, args, {
40
+ stdio: 'pipe',
41
+ shell: isWindows,
42
+ ...options
43
+ })
44
+
45
+ var stdout = []
46
+ var stderr = []
47
+
48
+ child.stdout.on('data', function (chunk) {
49
+ stdout.push(chunk)
50
+ })
51
+
52
+ child.stderr.on('data', function (chunk) {
53
+ stderr.push(chunk)
54
+ })
55
+
56
+ child.on('close', function (code) {
57
+ resolve({
58
+ code: code,
59
+ stdout: Buffer.concat(stdout).toString(),
60
+ stderr: Buffer.concat(stderr).toString()
61
+ })
62
+ })
63
+
64
+ child.on('error', function (err) {
65
+ reject(err)
66
+ })
67
+ })
68
+ }
69
+
70
+ /**
71
+ * Install Graphviz on macOS using Homebrew
72
+ */
73
+ async function installOnMac () {
74
+ console.log('🍺 Attempting to install Graphviz on macOS using Homebrew...')
75
+
76
+ // Check if Homebrew is installed
77
+ if (!commandExists('brew')) {
78
+ console.log('')
79
+ console.log('❌ Homebrew is not installed.')
80
+ console.log('')
81
+ console.log('Please install Homebrew first:')
82
+ console.log(' /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"')
83
+ console.log('')
84
+ console.log('Then run: brew install graphviz')
85
+ return false
86
+ }
87
+
88
+ try {
89
+ console.log('Installing Graphviz via Homebrew...')
90
+ var result = await execCommand('brew', ['install', 'graphviz'])
91
+
92
+ if (result.code === 0) {
93
+ console.log('✅ Graphviz installed successfully!')
94
+ return true
95
+ } else {
96
+ // Try upgrade if already installed
97
+ console.log('Attempting to upgrade Graphviz...')
98
+ var upgradeResult = await execCommand('brew', ['upgrade', 'graphviz'])
99
+ if (upgradeResult.code === 0) {
100
+ console.log('✅ Graphviz upgraded successfully!')
101
+ return true
102
+ } else {
103
+ console.log('⚠️ Installation failed. Please install manually:')
104
+ console.log(' brew install graphviz')
105
+ return false
106
+ }
107
+ }
108
+ } catch (err) {
109
+ console.log('❌ Error installing Graphviz:', err.message)
110
+ console.log('Please install manually: brew install graphviz')
111
+ return false
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Install Graphviz on Linux
117
+ */
118
+ async function installOnLinux () {
119
+ console.log('🐧 Attempting to install Graphviz on Linux...')
120
+
121
+ // Detect package manager
122
+ var packageManager = null
123
+ var packageName = 'graphviz'
124
+
125
+ var installArgs = null
126
+
127
+ if (commandExists('apt-get')) {
128
+ packageManager = 'apt-get'
129
+ installArgs = ['apt-get', 'install', '-y', packageName]
130
+ } else if (commandExists('yum')) {
131
+ packageManager = 'yum'
132
+ installArgs = ['yum', 'install', '-y', packageName]
133
+ } else if (commandExists('dnf')) {
134
+ packageManager = 'dnf'
135
+ installArgs = ['dnf', 'install', '-y', packageName]
136
+ } else if (commandExists('pacman')) {
137
+ packageManager = 'pacman'
138
+ installArgs = ['pacman', '-S', '--noconfirm', packageName]
139
+ } else if (commandExists('zypper')) {
140
+ packageManager = 'zypper'
141
+ installArgs = ['zypper', 'install', '-y', packageName]
142
+ } else {
143
+ console.log('❌ Could not detect package manager.')
144
+ console.log('Please install Graphviz manually using your system package manager.')
145
+ return false
146
+ }
147
+
148
+ console.log('Detected package manager: ' + packageManager)
149
+ console.log('Note: This requires sudo/administrator privileges.')
150
+
151
+ try {
152
+ // For apt-get, we need to run update first
153
+ if (packageManager === 'apt-get') {
154
+ console.log('Updating package list...')
155
+ var updateResult = await execCommand('sudo', ['apt-get', 'update'])
156
+ if (updateResult.code !== 0) {
157
+ console.log('⚠️ Failed to update package list. Trying installation anyway...')
158
+ }
159
+ }
160
+
161
+ console.log('Installing Graphviz...')
162
+ var result = await execCommand('sudo', installArgs)
163
+
164
+ if (result.code === 0) {
165
+ console.log('✅ Graphviz installed successfully!')
166
+ return true
167
+ } else {
168
+ console.log('⚠️ Installation failed. Please install manually:')
169
+ if (packageManager === 'apt-get') {
170
+ console.log(' sudo apt-get update && sudo apt-get install -y graphviz')
171
+ } else {
172
+ console.log(' sudo ' + installArgs.join(' '))
173
+ }
174
+ return false
175
+ }
176
+ } catch (err) {
177
+ console.log('❌ Error installing Graphviz:', err.message)
178
+ console.log('Please install manually:')
179
+ if (packageManager === 'apt-get') {
180
+ console.log(' sudo apt-get update && sudo apt-get install -y graphviz')
181
+ } else {
182
+ console.log(' sudo ' + installArgs.join(' '))
183
+ }
184
+ return false
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Install Graphviz on Windows
190
+ */
191
+ async function installOnWindows () {
192
+ console.log('🪟 Attempting to install Graphviz on Windows...')
193
+
194
+ // Try Chocolatey first
195
+ if (commandExists('choco')) {
196
+ console.log('Detected Chocolatey package manager.')
197
+ try {
198
+ console.log('Installing Graphviz via Chocolatey...')
199
+ var result = await execCommand('choco', ['install', 'graphviz', '-y'], {
200
+ shell: true
201
+ })
202
+
203
+ if (result.code === 0 || result.stdout.indexOf('installed') !== -1) {
204
+ console.log('✅ Graphviz installed successfully!')
205
+ return true
206
+ }
207
+ } catch (err) {
208
+ console.log('⚠️ Chocolatey installation failed, trying other methods...')
209
+ }
210
+ }
211
+
212
+ // Try Winget
213
+ if (commandExists('winget')) {
214
+ console.log('Detected Winget package manager.')
215
+ try {
216
+ console.log('Installing Graphviz via Winget...')
217
+ var wingetResult = await execCommand('winget', ['install', 'Graphviz.Graphviz', '--accept-package-agreements', '--accept-source-agreements'], {
218
+ shell: true
219
+ })
220
+
221
+ if (wingetResult.code === 0) {
222
+ console.log('✅ Graphviz installed successfully!')
223
+ return true
224
+ }
225
+ } catch (err) {
226
+ console.log('⚠️ Winget installation failed...')
227
+ }
228
+ }
229
+
230
+ // If both failed, provide manual instructions
231
+ console.log('')
232
+ console.log('❌ Could not automatically install Graphviz.')
233
+ console.log('')
234
+ console.log('Please install Graphviz manually:')
235
+ console.log('')
236
+ console.log('Option 1: Using Chocolatey (if installed):')
237
+ console.log(' choco install graphviz -y')
238
+ console.log('')
239
+ console.log('Option 2: Using Winget (Windows 10/11):')
240
+ console.log(' winget install Graphviz.Graphviz')
241
+ console.log('')
242
+ console.log('Option 3: Download installer:')
243
+ console.log(' https://graphviz.org/download/')
244
+ console.log('')
245
+
246
+ return false
247
+ }
248
+
249
+ /**
250
+ * Main installation function
251
+ */
252
+ async function installGraphviz () {
253
+ console.log('')
254
+ console.log('🔍 Checking if Graphviz is already installed...')
255
+ console.log('')
256
+
257
+ // First check if Graphviz is already installed
258
+ var detected = dotResolver.resolveDotExecutable({ dotPath: null })
259
+ if (detected) {
260
+ console.log('✅ Graphviz is already installed at: ' + detected)
261
+ console.log('')
262
+ try {
263
+ var testResult = await execCommand(detected, ['-V'])
264
+ if (testResult.code === 0 || testResult.stdout) {
265
+ console.log('Version info:')
266
+ console.log(testResult.stdout.split('\n')[0])
267
+ }
268
+ } catch (e) {
269
+ // Ignore
270
+ }
271
+ return true
272
+ }
273
+
274
+ console.log('❌ Graphviz is not installed.')
275
+ console.log('')
276
+
277
+ // Attempt automatic installation based on platform
278
+ var installed = false
279
+
280
+ if (isMac) {
281
+ installed = await installOnMac()
282
+ } else if (isLinux) {
283
+ installed = await installOnLinux()
284
+ } else if (isWindows) {
285
+ installed = await installOnWindows()
286
+ } else {
287
+ console.log('❌ Unsupported platform: ' + platform)
288
+ console.log('Please install Graphviz manually.')
289
+ return false
290
+ }
291
+
292
+ if (installed) {
293
+ // Verify installation
294
+ console.log('')
295
+ console.log('🔍 Verifying installation...')
296
+ var newDetected = dotResolver.resolveDotExecutable({ dotPath: null })
297
+ if (newDetected) {
298
+ console.log('✅ Graphviz is now available at: ' + newDetected)
299
+ return true
300
+ } else {
301
+ console.log('⚠️ Graphviz was installed but cannot be found.')
302
+ console.log('You may need to restart your terminal or add it to PATH.')
303
+ return false
304
+ }
305
+ }
306
+
307
+ return false
308
+ }
309
+
310
+ // Run if called directly
311
+ if (require.main === module) {
312
+ installGraphviz()
313
+ .then(function (success) {
314
+ if (success) {
315
+ console.log('')
316
+ console.log('✅ Graphviz installation completed successfully!')
317
+ process.exit(0)
318
+ } else {
319
+ console.log('')
320
+ console.log('⚠️ Automatic installation failed. Please install Graphviz manually.')
321
+ process.exit(1)
322
+ }
323
+ })
324
+ .catch(function (err) {
325
+ console.error('❌ Error:', err.message)
326
+ process.exit(1)
327
+ })
328
+ }
329
+
330
+ module.exports = {
331
+ installGraphviz: installGraphviz,
332
+ installOnMac: installOnMac,
333
+ installOnLinux: installOnLinux,
334
+ installOnWindows: installOnWindows
335
+ }