node-plantuml-2 1.1.3 → 1.1.5
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/lib/dot-resolver.js +96 -17
- package/lib/node-plantuml.js +35 -7
- package/lib/plantuml-executor.js +11 -2
- package/package.json +9 -11
- package/scripts/install-graphviz.js +4 -4
package/lib/dot-resolver.js
CHANGED
|
@@ -24,18 +24,59 @@ function resolveBundledGraphviz () {
|
|
|
24
24
|
// Try to resolve the package
|
|
25
25
|
var pkgPath
|
|
26
26
|
try {
|
|
27
|
-
// Try
|
|
27
|
+
// Method 1: Try require.resolve (works in most cases, including external projects)
|
|
28
28
|
var pkgJsonPath = require.resolve(pkgName + '/package.json')
|
|
29
29
|
pkgPath = path.dirname(pkgJsonPath)
|
|
30
30
|
} catch (e) {
|
|
31
|
-
// Package might not be installed (optional dependency)
|
|
32
|
-
// Try to find it
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
// Method 2: Package might not be installed (optional dependency)
|
|
32
|
+
// Try to find it by locating node-plantuml-2 package first, then look in its parent node_modules
|
|
33
|
+
try {
|
|
34
|
+
// Find where node-plantuml-2 is installed
|
|
35
|
+
var nodePlantumlPath = require.resolve('node-plantuml-2')
|
|
36
|
+
// Get the node_modules directory that contains node-plantuml-2
|
|
37
|
+
// node-plantuml-2 is at: .../node_modules/node-plantuml-2/lib/...
|
|
38
|
+
// So node_modules is at: .../node_modules/
|
|
39
|
+
var nodeModulesDir = path.dirname(path.dirname(nodePlantumlPath))
|
|
40
|
+
|
|
41
|
+
// For scoped packages like @node-plantuml-2/graphviz-win32-x64,
|
|
42
|
+
// the path structure is: node_modules/@node-plantuml-2/graphviz-win32-x64/
|
|
43
|
+
// So we need to handle the @scope/package format
|
|
44
|
+
var possiblePath = path.join(nodeModulesDir, pkgName)
|
|
45
|
+
if (fs.existsSync(path.join(possiblePath, 'package.json'))) {
|
|
46
|
+
pkgPath = possiblePath
|
|
47
|
+
} else {
|
|
48
|
+
// Method 3: Try in current package's node_modules (for development)
|
|
49
|
+
var thisPkgPath = path.join(__dirname, '..')
|
|
50
|
+
var devPath = path.join(thisPkgPath, 'node_modules', pkgName)
|
|
51
|
+
if (fs.existsSync(path.join(devPath, 'package.json'))) {
|
|
52
|
+
pkgPath = devPath
|
|
53
|
+
} else {
|
|
54
|
+
// Method 4: Recursive search up the directory tree
|
|
55
|
+
var currentDir = thisPkgPath
|
|
56
|
+
var found = false
|
|
57
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
58
|
+
var searchPath = path.join(currentDir, 'node_modules', pkgName)
|
|
59
|
+
if (fs.existsSync(path.join(searchPath, 'package.json'))) {
|
|
60
|
+
pkgPath = searchPath
|
|
61
|
+
found = true
|
|
62
|
+
break
|
|
63
|
+
}
|
|
64
|
+
currentDir = path.dirname(currentDir)
|
|
65
|
+
}
|
|
66
|
+
if (!found) {
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
} catch (resolveErr) {
|
|
72
|
+
// If we can't even resolve node-plantuml-2, try local fallback
|
|
73
|
+
var thisPkgPath = path.join(__dirname, '..')
|
|
74
|
+
var possiblePath = path.join(thisPkgPath, 'node_modules', pkgName)
|
|
75
|
+
if (fs.existsSync(path.join(possiblePath, 'package.json'))) {
|
|
76
|
+
pkgPath = possiblePath
|
|
77
|
+
} else {
|
|
78
|
+
return null
|
|
79
|
+
}
|
|
39
80
|
}
|
|
40
81
|
}
|
|
41
82
|
|
|
@@ -82,14 +123,18 @@ function getBundledGraphvizLibPath (dotPath) {
|
|
|
82
123
|
}
|
|
83
124
|
|
|
84
125
|
try {
|
|
126
|
+
// Normalize path separators for checking
|
|
127
|
+
var normalizedPath = dotPath.replace(/\\/g, '/')
|
|
128
|
+
|
|
85
129
|
// Check if this is a bundled Graphviz path
|
|
86
130
|
// Bundled path format: .../node_modules/@node-plantuml-2/graphviz-*/graphviz/bin/dot
|
|
87
131
|
// Handle both / and \ path separators (Windows uses \)
|
|
88
|
-
var isBundled =
|
|
89
|
-
|
|
132
|
+
var isBundled = normalizedPath.includes('@node-plantuml-2/graphviz-') &&
|
|
133
|
+
normalizedPath.includes('/graphviz/bin/')
|
|
90
134
|
if (isBundled) {
|
|
91
135
|
// Extract the graphviz directory
|
|
92
|
-
|
|
136
|
+
// Go up from bin/ to graphviz/
|
|
137
|
+
var graphvizDir = path.dirname(path.dirname(dotPath))
|
|
93
138
|
var libDir = path.join(graphvizDir, 'lib')
|
|
94
139
|
|
|
95
140
|
if (fs.existsSync(libDir)) {
|
|
@@ -126,20 +171,24 @@ function getGraphvizPackageName (platform, arch) {
|
|
|
126
171
|
}
|
|
127
172
|
|
|
128
173
|
/**
|
|
129
|
-
* Resolve Graphviz dot executable path
|
|
174
|
+
* Resolve Graphviz dot executable path
|
|
130
175
|
*
|
|
131
176
|
* Priority order:
|
|
132
177
|
* 1. options.dotPath (user-specified)
|
|
133
|
-
* 2. Bundled Graphviz (from optional dependencies)
|
|
134
|
-
*
|
|
135
|
-
*
|
|
178
|
+
* 2. Bundled Graphviz (from optional dependencies) - REQUIRED
|
|
179
|
+
*
|
|
180
|
+
* NOTE: We ONLY use bundled Graphviz packages. System Graphviz is NOT used.
|
|
181
|
+
* This ensures consistent behavior across all environments.
|
|
136
182
|
*
|
|
137
183
|
* @param {Object} options - Options object
|
|
138
184
|
* @param {string} options.dotPath - User-specified dot path (highest priority)
|
|
185
|
+
* @param {boolean} options.allowSystemFallback - If true, allow system Graphviz as fallback (for install scripts only)
|
|
139
186
|
* @returns {string|null} - Path to dot executable, or null if not found
|
|
187
|
+
* @throws {Error} - If bundled Graphviz is not found and allowSystemFallback is false
|
|
140
188
|
*/
|
|
141
189
|
function resolveDotExecutable (options) {
|
|
142
190
|
options = options || {}
|
|
191
|
+
var allowSystemFallback = options.allowSystemFallback === true
|
|
143
192
|
|
|
144
193
|
// Priority 1: User-specified dot path
|
|
145
194
|
if (options.dotPath) {
|
|
@@ -149,12 +198,42 @@ function resolveDotExecutable (options) {
|
|
|
149
198
|
}
|
|
150
199
|
}
|
|
151
200
|
|
|
152
|
-
// Priority 2: Bundled Graphviz from optional dependencies
|
|
201
|
+
// Priority 2: Bundled Graphviz from optional dependencies (REQUIRED)
|
|
153
202
|
var bundledGraphviz = resolveBundledGraphviz()
|
|
154
203
|
if (bundledGraphviz) {
|
|
155
204
|
return bundledGraphviz
|
|
156
205
|
}
|
|
157
206
|
|
|
207
|
+
// If bundled Graphviz is not found, we should NOT fallback to system
|
|
208
|
+
// This ensures all users use the same Graphviz version
|
|
209
|
+
if (!allowSystemFallback) {
|
|
210
|
+
var platform = os.platform()
|
|
211
|
+
var arch = os.arch()
|
|
212
|
+
var pkgName = getGraphvizPackageName(platform, arch)
|
|
213
|
+
|
|
214
|
+
if (pkgName) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
'Bundled Graphviz not found. Please install the Graphviz runtime package:\n' +
|
|
217
|
+
' npm install ' + pkgName + '\n\n' +
|
|
218
|
+
'This package should be automatically installed via optionalDependencies.\n' +
|
|
219
|
+
'If it failed to install, please check:\n' +
|
|
220
|
+
' 1. Your platform is supported: ' + platform + ' ' + arch + '\n' +
|
|
221
|
+
' 2. Network connection during npm install\n' +
|
|
222
|
+
' 3. npm install logs for errors\n\n' +
|
|
223
|
+
'Alternatively, you can specify a custom Graphviz path:\n' +
|
|
224
|
+
' plantuml.generate(code, { dotPath: "/path/to/dot" })'
|
|
225
|
+
)
|
|
226
|
+
} else {
|
|
227
|
+
throw new Error(
|
|
228
|
+
'Graphviz is required but not available.\n' +
|
|
229
|
+
'Your platform (' + platform + ' ' + arch + ') is not supported.\n' +
|
|
230
|
+
'Please install Graphviz manually and specify the path:\n' +
|
|
231
|
+
' plantuml.generate(code, { dotPath: "/path/to/dot" })'
|
|
232
|
+
)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// System fallback (ONLY for install scripts, NOT for runtime)
|
|
158
237
|
// Priority 3: Common installation paths (platform-specific)
|
|
159
238
|
var commonPaths = getCommonDotPaths()
|
|
160
239
|
for (var i = 0; i < commonPaths.length; i++) {
|
package/lib/node-plantuml.js
CHANGED
|
@@ -215,11 +215,20 @@ function joinOptions (argv, options) {
|
|
|
215
215
|
argv.push(file)
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
-
// Auto-detect dot path if not specified
|
|
218
|
+
// Auto-detect dot path if not specified (ONLY from bundled Graphviz)
|
|
219
219
|
if (!options.dot) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
try {
|
|
221
|
+
var detectedDot = dotResolver.resolveDotExecutable({ dotPath: null })
|
|
222
|
+
if (detectedDot) {
|
|
223
|
+
options.dot = detectedDot
|
|
224
|
+
}
|
|
225
|
+
} catch (err) {
|
|
226
|
+
// Graphviz is optional for most diagram types
|
|
227
|
+
// Only required for certain diagram types (e.g., some activity diagrams)
|
|
228
|
+
// If not found, PlantUML will handle it gracefully
|
|
229
|
+
if (process.env.DEBUG_PLANTUML) {
|
|
230
|
+
console.warn('[DEBUG] Graphviz not found, some diagram types may not work:', err.message)
|
|
231
|
+
}
|
|
223
232
|
}
|
|
224
233
|
}
|
|
225
234
|
|
|
@@ -384,15 +393,34 @@ module.exports.decode = function (encoded, callback) {
|
|
|
384
393
|
}
|
|
385
394
|
|
|
386
395
|
module.exports.testdot = function (callback) {
|
|
387
|
-
// Auto-detect dot path and pass it to PlantUML
|
|
388
|
-
var detectedDot =
|
|
396
|
+
// Auto-detect dot path and pass it to PlantUML (ONLY from bundled Graphviz)
|
|
397
|
+
var detectedDot = null
|
|
398
|
+
try {
|
|
399
|
+
detectedDot = dotResolver.resolveDotExecutable({ dotPath: null })
|
|
400
|
+
} catch (err) {
|
|
401
|
+
// If bundled Graphviz is not found, return error
|
|
402
|
+
if (typeof callback === 'function') {
|
|
403
|
+
return callback(new Error('Graphviz not found: ' + err.message))
|
|
404
|
+
}
|
|
405
|
+
throw err
|
|
406
|
+
}
|
|
407
|
+
|
|
389
408
|
var argv = [TESTDOT]
|
|
390
409
|
if (detectedDot) {
|
|
410
|
+
// Ensure dot path is absolute - PlantUML Java process needs absolute path
|
|
411
|
+
var absoluteDotPath = path.resolve(detectedDot)
|
|
412
|
+
// Normalize path separators for the platform
|
|
413
|
+
if (process.platform === 'win32') {
|
|
414
|
+
absoluteDotPath = absoluteDotPath.replace(/\//g, '\\')
|
|
415
|
+
} else {
|
|
416
|
+
absoluteDotPath = absoluteDotPath.replace(/\\/g, '/')
|
|
417
|
+
}
|
|
391
418
|
argv.push(DOT)
|
|
392
|
-
argv.push(
|
|
419
|
+
argv.push(absoluteDotPath)
|
|
393
420
|
}
|
|
394
421
|
|
|
395
422
|
// Don't pass callback to exec - we need to handle output ourselves
|
|
423
|
+
// Pass empty options object to ensure environment variables are set correctly
|
|
396
424
|
var child = plantumlExecutor.exec(argv, undefined, {}, undefined)
|
|
397
425
|
|
|
398
426
|
var stdoutChunks = []
|
package/lib/plantuml-executor.js
CHANGED
|
@@ -102,9 +102,18 @@ function execWithSpawn (argv, cwd, options, cb) {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
// If no dot path in argv, try to detect it
|
|
105
|
+
// If no dot path in argv, try to detect it (ONLY from bundled Graphviz)
|
|
106
106
|
if (!dotPath) {
|
|
107
|
-
|
|
107
|
+
try {
|
|
108
|
+
dotPath = dotResolver.resolveDotExecutable({ dotPath: null })
|
|
109
|
+
} catch (err) {
|
|
110
|
+
// If bundled Graphviz is not found, log error but continue
|
|
111
|
+
// PlantUML will work without Graphviz for most diagram types
|
|
112
|
+
if (process.env.DEBUG_PLANTUML) {
|
|
113
|
+
console.warn('[DEBUG] Graphviz not found:', err.message)
|
|
114
|
+
}
|
|
115
|
+
// dotPath remains null, PlantUML will handle it
|
|
116
|
+
}
|
|
108
117
|
}
|
|
109
118
|
|
|
110
119
|
// CRITICAL FIX: Ensure dot path is absolute and properly formatted
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-plantuml-2",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
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.
|
|
30
|
-
"@node-plantuml-2/jre-darwin-arm64": "^1.1.
|
|
31
|
-
"@node-plantuml-2/jre-linux-x64": "^1.1.
|
|
32
|
-
"@node-plantuml-2/graphviz-win32-x64": "^1.1.
|
|
33
|
-
"@node-plantuml-2/graphviz-darwin-arm64": "^1.1.
|
|
34
|
-
"@node-plantuml-2/graphviz-darwin-x64": "^1.1.
|
|
35
|
-
"@node-plantuml-2/graphviz-linux-x64": "^1.1.
|
|
29
|
+
"@node-plantuml-2/jre-win32-x64": "^1.1.5",
|
|
30
|
+
"@node-plantuml-2/jre-darwin-arm64": "^1.1.5",
|
|
31
|
+
"@node-plantuml-2/jre-linux-x64": "^1.1.5",
|
|
32
|
+
"@node-plantuml-2/graphviz-win32-x64": "^1.1.5",
|
|
33
|
+
"@node-plantuml-2/graphviz-darwin-arm64": "^1.1.5",
|
|
34
|
+
"@node-plantuml-2/graphviz-darwin-x64": "^1.1.5",
|
|
35
|
+
"@node-plantuml-2/graphviz-linux-x64": "^1.1.5"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"chai": "^4.x",
|
|
@@ -62,9 +62,7 @@
|
|
|
62
62
|
"test:integration": "node test/test-integration-full.js",
|
|
63
63
|
"build": "node nail/build.js",
|
|
64
64
|
"build:all": "node scripts/build-all.js",
|
|
65
|
-
"build:all:jar-only": "node scripts/get-plantuml-jar.js --latest"
|
|
66
|
-
"test:graphviz": "node scripts/test-graphviz-build.js",
|
|
67
|
-
"test:graphviz:build": "node scripts/test-graphviz-build.js"
|
|
65
|
+
"build:all:jar-only": "node scripts/get-plantuml-jar.js --latest"
|
|
68
66
|
},
|
|
69
67
|
"bin": {
|
|
70
68
|
"puml": "index.js"
|
|
@@ -254,8 +254,8 @@ async function installGraphviz () {
|
|
|
254
254
|
console.log('🔍 Checking if Graphviz is already installed...')
|
|
255
255
|
console.log('')
|
|
256
256
|
|
|
257
|
-
// First check if Graphviz is already installed
|
|
258
|
-
var detected = dotResolver.resolveDotExecutable({ dotPath: null })
|
|
257
|
+
// First check if Graphviz is already installed (allow system fallback for install script)
|
|
258
|
+
var detected = dotResolver.resolveDotExecutable({ dotPath: null, allowSystemFallback: true })
|
|
259
259
|
if (detected) {
|
|
260
260
|
console.log('✅ Graphviz is already installed at: ' + detected)
|
|
261
261
|
console.log('')
|
|
@@ -290,10 +290,10 @@ async function installGraphviz () {
|
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
if (installed) {
|
|
293
|
-
// Verify installation
|
|
293
|
+
// Verify installation (allow system fallback for install script)
|
|
294
294
|
console.log('')
|
|
295
295
|
console.log('🔍 Verifying installation...')
|
|
296
|
-
var newDetected = dotResolver.resolveDotExecutable({ dotPath: null })
|
|
296
|
+
var newDetected = dotResolver.resolveDotExecutable({ dotPath: null, allowSystemFallback: true })
|
|
297
297
|
if (newDetected) {
|
|
298
298
|
console.log('✅ Graphviz is now available at: ' + newDetected)
|
|
299
299
|
return true
|