diff --git a/packages/plugin-npm-cli/sources/npmAuditUtils.ts b/packages/plugin-npm-cli/sources/npmAuditUtils.ts index 5255bc640dc7..63359f484fa9 100644 --- a/packages/plugin-npm-cli/sources/npmAuditUtils.ts +++ b/packages/plugin-npm-cli/sources/npmAuditUtils.ts @@ -28,8 +28,12 @@ export function getReportTree(result: npmAuditTypes.AuditExtendedResponse) { for (const [packageName, advisories] of miscUtils.sortMap(Object.entries(result), advisory => advisory[0])) { for (const advisory of miscUtils.sortMap(advisories, advisory => `${advisory.id}`)) { auditTreeChildren[`${packageName}/${advisory.id}`] = { - label: `${packageName} - #${advisory.id}`, + value: formatUtils.tuple(formatUtils.Type.IDENT, structUtils.parseIdent(packageName)), children: { + ID: { + label: `ID`, + value: formatUtils.tuple(formatUtils.Type.NUMBER, advisory.id), + }, Issue: { label: `Issue`, value: formatUtils.tuple(formatUtils.Type.NO_HINT, advisory.title), diff --git a/packages/yarnpkg-core/sources/treeUtils.ts b/packages/yarnpkg-core/sources/treeUtils.ts index 0ad81db1d5b1..80025c1a2633 100644 --- a/packages/yarnpkg-core/sources/treeUtils.ts +++ b/packages/yarnpkg-core/sources/treeUtils.ts @@ -24,6 +24,7 @@ export type TreeifyNode = { export function treeNodeToTreeify(printTree: TreeNode, {configuration}: {configuration: Configuration}) { const target = {}; + let n = 0; const copyTree = (printNode: Array | TreeMap, targetNode: TreeifyNode) => { const iterator = Array.isArray(printNode) @@ -40,7 +41,9 @@ export function treeNodeToTreeify(printTree: TreeNode, {configuration}: {configu finalParts.push(formatUtils.applyStyle(configuration, `${key}`, formatUtils.Style.BOLD)); const finalLabel = finalParts.join(`: `); - const createdNode = targetNode[finalLabel] = {}; + + const uniquePrefix = `\0${n++}\0`; + const createdNode = targetNode[`${uniquePrefix}${finalLabel}`] = {}; if (typeof children !== `undefined`) { copyTree(children, createdNode); @@ -73,7 +76,7 @@ export function treeNodeToJson(printTree: TreeNode) { : {}; for (const [key, child] of iterator) - targetChildren[key] = copyTree(child); + targetChildren[cleanKey(key)] = copyTree(child); if (typeof printNode.value === `undefined`) return targetChildren; @@ -106,6 +109,8 @@ export function emitTree(tree: TreeNode, {configuration, stdout, json, separator let treeOutput = asTree(treeNodeToTreeify(tree, {configuration}) as any, false, false); + treeOutput = treeOutput.replace(/\0[0-9]+\0/g, ``); + // A slight hack to add line returns between two top-level entries if (separators >= 1) treeOutput = treeOutput.replace(/^([├└]─)/gm, `│\n$1`).replace(/^│\n/, ``); @@ -120,3 +125,7 @@ export function emitTree(tree: TreeNode, {configuration, stdout, json, separator stdout.write(treeOutput); } + +function cleanKey(key: string | number) { + return typeof key === `string` ? key.replace(/^\0[0-9]+\0/, ``) : key; +}