diff --git a/jig-core/src/main/resources/templates/assets/package.js b/jig-core/src/main/resources/templates/assets/package.js index f4662e2b7..6b9c5a994 100644 --- a/jig-core/src/main/resources/templates/assets/package.js +++ b/jig-core/src/main/resources/templates/assets/package.js @@ -562,10 +562,14 @@ function renderPackageDiagram(packageFilterFqn, relatedFilterFqn) { } }); - const addNodeLines = nodeId => { - const label = nodeLabelById.get(nodeId); - lines.push(`${nodeId}["${escapeMermaidText(label)}"]`); + const addNodeLines = (nodeId, parentSubgraphFqn) => { const fqn = diagramNodeIdToFqn.get(nodeId); + let displayLabel = nodeLabelById.get(nodeId); + + if (displayLabel === fqn && parentSubgraphFqn && fqn.startsWith(`${parentSubgraphFqn}.`)) { + displayLabel = fqn.substring(parentSubgraphFqn.length + 1); + } + lines.push(`${nodeId}["${escapeMermaidText(displayLabel)}"]`); const tooltip = fqn ? escapeMermaidText(fqn) : ''; lines.push(`click ${nodeId} filterPackageDiagram "${tooltip}"`); if (fqn && parentFqns.has(fqn)) { @@ -591,27 +595,27 @@ function renderPackageDiagram(packageFilterFqn, relatedFilterFqn) { } current.nodes.push(nodeIdByFqn.get(fqn)); }); - const renderGroup = (group, isRoot) => { - group.nodes.forEach(addNodeLines); + const renderGroup = (group, isRoot, parentSubgraphFqnForNodes) => { + group.nodes.forEach(nodeId => addNodeLines(nodeId, parentSubgraphFqnForNodes)); const childKeys = Array.from(group.children.keys()).sort(); if (isRoot && group.nodes.length === 0 && childKeys.length === 1) { - renderGroup(group.children.get(childKeys[0]), false); + renderGroup(group.children.get(childKeys[0]), false, parentSubgraphFqnForNodes); return; } childKeys.forEach(key => { const child = group.children.get(key); const childNodeCount = child.nodes.length + child.children.size; if (childNodeCount <= 1) { - renderGroup(child, false); + renderGroup(child, false, parentSubgraphFqnForNodes); return; } const groupId = `G${groupIndex++}`; lines.push(`subgraph ${groupId}["${escapeMermaidText(child.key)}"]`); - renderGroup(child, false); + renderGroup(child, false, child.key); lines.push('end'); }); }; - renderGroup(rootGroup, true); + renderGroup(rootGroup, true, rootGroup.key); if (parentFqns.size > 0) { lines.push('classDef parentPackage fill:#ffffde,stroke:#aaaa00,stroke-width:2px'); } diff --git a/jig-core/src/test/js/package.test.js b/jig-core/src/test/js/package.test.js index e05b8e709..3d708eb0c 100644 --- a/jig-core/src/test/js/package.test.js +++ b/jig-core/src/test/js/package.test.js @@ -679,6 +679,41 @@ test.describe('package.js', () => { const mutual = doc.getElementById('mutual-dependency-list'); assert.equal(mutual.children.length > 0, true); }); + + test('renderPackageDiagram: サブグラフ内のFQNノードラベルが省略される', () => { + const doc = setupDocument(); + const diagram = setupDiagramEnvironment(doc); + setPackageData(doc, { + packages: [ + {fqn: 'com.example', name: 'example', classCount: 1}, + {fqn: 'com.example.domain', name: 'domain', classCount: 1}, + {fqn: 'com.example.domain.model', classCount: 1}, // No 'name' property + {fqn: 'com.example.domain.repository', name: 'repository', classCount: 1}, + {fqn: 'com.example.service', name: 'service', classCount: 1}, + ], + relations: [ + {from: 'com.example.domain.model', to: 'com.example.domain.repository'}, + {from: 'com.example.service', to: 'com.example.domain'}, + ], + }); + + pkg.setAggregationDepth(0); // Set to no aggregation to ensure full hierarchy is built + pkg.renderPackageDiagram(null, null); + + const diagramContent = diagram.textContent; + + // Match subgraph creation for com.example.domain (using regex for groupId) + assert.ok(/subgraph G\d+\["com\.example\.domain"]/.test(diagramContent), 'Expected subgraph for com.example.domain'); + + // Check for nodes inside this subgraph: + // com.example.domain.model (FQN, should be shortened to 'model') + assert.ok(/P\d+\["model"]/.test(diagramContent), 'Expected "com.example.domain.model" to be shortened to "model"'); + // com.example.domain.repository (has 'name', should remain 'repository') + assert.ok(/P\d+\["repository"]/.test(diagramContent), 'Expected "com.example.domain.repository" to remain "repository"'); + + // Verify that 'com.example.service' is also present and correctly labeled + assert.ok(/P\d+\["service"]/.test(diagramContent), 'Expected "com.example.service" to be labeled "service"'); + }); }); test.describe('分岐/エラー', () => {