From 5f17e1c32a9d257abc497ddbe00bf16df6fa9d7d Mon Sep 17 00:00:00 2001 From: irof Date: Wed, 4 Feb 2026 23:48:03 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=B5=E3=83=96=E3=82=B0=E3=83=A9=E3=83=95?= =?UTF-8?q?=E5=86=85=E3=81=AE=E3=83=8E=E3=83=BC=E3=83=89=E5=90=8D=E3=81=8C?= =?UTF-8?q?FQN=E3=81=AE=E5=A0=B4=E5=90=88=E3=81=AB=E7=9F=AD=E7=B8=AE?= =?UTF-8?q?=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/templates/assets/package.js | 22 +++++++----- jig-core/src/test/js/package.test.js | 35 +++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) 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('分岐/エラー', () => {