Release 0.0.17
This commit is contained in:
@@ -76,6 +76,11 @@
|
|||||||
"Target": "Ziel",
|
"Target": "Ziel",
|
||||||
"Source": "Quelle"
|
"Source": "Quelle"
|
||||||
},
|
},
|
||||||
|
"Table": {
|
||||||
|
"Severity": "Stufe",
|
||||||
|
"References": "Refs",
|
||||||
|
"Note": "Hinweis"
|
||||||
|
},
|
||||||
"FindingKind": {
|
"FindingKind": {
|
||||||
"non-package-to-package-reference": "Unverankerte Paketziele",
|
"non-package-to-package-reference": "Unverankerte Paketziele",
|
||||||
"broken-reference": "Kaputte Ziele",
|
"broken-reference": "Kaputte Ziele",
|
||||||
|
|||||||
@@ -76,6 +76,11 @@
|
|||||||
"Target": "Target",
|
"Target": "Target",
|
||||||
"Source": "Source"
|
"Source": "Source"
|
||||||
},
|
},
|
||||||
|
"Table": {
|
||||||
|
"Severity": "Severity",
|
||||||
|
"References": "Refs",
|
||||||
|
"Note": "Note"
|
||||||
|
},
|
||||||
"FindingKind": {
|
"FindingKind": {
|
||||||
"non-package-to-package-reference": "Unanchored package targets",
|
"non-package-to-package-reference": "Unanchored package targets",
|
||||||
"broken-reference": "Broken targets",
|
"broken-reference": "Broken targets",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"id": "kosmos-storage-audit",
|
"id": "kosmos-storage-audit",
|
||||||
"title": "Kosmos Storage Audit",
|
"title": "Kosmos Storage Audit",
|
||||||
"description": "Analyzes media references and risky storage locations across Foundry data and public roots.",
|
"description": "Analyzes media references and risky storage locations across Foundry data and public roots.",
|
||||||
"version": "0.0.16",
|
"version": "0.0.17",
|
||||||
"compatibility": {
|
"compatibility": {
|
||||||
"minimum": "13",
|
"minimum": "13",
|
||||||
"verified": "13"
|
"verified": "13"
|
||||||
|
|||||||
@@ -267,23 +267,11 @@ function renderGroupedFindingList(groupedFindings, hasAnalysis, loading, showAll
|
|||||||
sections.push(renderGroupedSection(
|
sections.push(renderGroupedSection(
|
||||||
localize("KSA.Section.UnanchoredPackageTargets"),
|
localize("KSA.Section.UnanchoredPackageTargets"),
|
||||||
localize("KSA.Section.UnanchoredPackageTargetsDesc"),
|
localize("KSA.Section.UnanchoredPackageTargetsDesc"),
|
||||||
groupedFindings.nonPackageToPackage,
|
renderGroupedTable(groupedFindings.nonPackageToPackage, {
|
||||||
group => `
|
includeOwner: true,
|
||||||
<article class="storage-audit__finding severity-${group.severity}">
|
includeReason: true,
|
||||||
<header>
|
includeSources: true
|
||||||
<span class="storage-audit__severity">${severityLabel(group.severity)}</span>
|
})
|
||||||
<strong>${formatCount(group.count, "KSA.Summary.References")}</strong>
|
|
||||||
</header>
|
|
||||||
<p><code>${escapeHtml(group.target)}</code></p>
|
|
||||||
<p>${escapeHtml(group.shortReason)}</p>
|
|
||||||
<dl>
|
|
||||||
<div><dt>${localize("KSA.Field.OwnerPackage")}</dt><dd><code>${escapeHtml(group.ownerLabel)}</code></dd></div>
|
|
||||||
<div><dt>${localize("KSA.Field.Assessment")}</dt><dd>${escapeHtml(group.explanation)}</dd></div>
|
|
||||||
</dl>
|
|
||||||
<p class="storage-audit__recommendation">${escapeHtml(group.recommendation)}</p>
|
|
||||||
${renderSampleSources(group.sources)}
|
|
||||||
</article>
|
|
||||||
`
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,20 +279,11 @@ function renderGroupedFindingList(groupedFindings, hasAnalysis, loading, showAll
|
|||||||
sections.push(renderGroupedSection(
|
sections.push(renderGroupedSection(
|
||||||
localize("KSA.Section.BrokenTargets"),
|
localize("KSA.Section.BrokenTargets"),
|
||||||
localize("KSA.Section.BrokenTargetsDesc"),
|
localize("KSA.Section.BrokenTargetsDesc"),
|
||||||
groupedFindings.brokenReferences,
|
renderGroupedTable(groupedFindings.brokenReferences, {
|
||||||
group => `
|
includeOwner: false,
|
||||||
<article class="storage-audit__finding severity-${group.severity}">
|
includeReason: true,
|
||||||
<header>
|
includeSources: true
|
||||||
<span class="storage-audit__severity">${severityLabel(group.severity)}</span>
|
})
|
||||||
<strong>${formatCount(group.count, "KSA.Summary.References")}</strong>
|
|
||||||
</header>
|
|
||||||
<p><code>${escapeHtml(group.target)}</code></p>
|
|
||||||
<p>${escapeHtml(group.shortReason)}</p>
|
|
||||||
${group.targetKind === "wildcard" ? `<p>${localize("KSA.Finding.WildcardNoMatch")}</p>` : ""}
|
|
||||||
<p class="storage-audit__recommendation">${escapeHtml(group.recommendation)}</p>
|
|
||||||
${renderSampleSources(group.sources)}
|
|
||||||
</article>
|
|
||||||
`
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,18 +291,11 @@ function renderGroupedFindingList(groupedFindings, hasAnalysis, loading, showAll
|
|||||||
sections.push(renderGroupedSection(
|
sections.push(renderGroupedSection(
|
||||||
localize("KSA.Section.OrphanCandidates"),
|
localize("KSA.Section.OrphanCandidates"),
|
||||||
localize("KSA.Section.OrphanCandidatesDesc"),
|
localize("KSA.Section.OrphanCandidatesDesc"),
|
||||||
groupedFindings.orphans,
|
renderGroupedTable(groupedFindings.orphans, {
|
||||||
group => `
|
includeOwner: false,
|
||||||
<article class="storage-audit__finding severity-${group.severity}">
|
includeReason: true,
|
||||||
<header>
|
includeSources: false
|
||||||
<span class="storage-audit__severity">${severityLabel(group.severity)}</span>
|
})
|
||||||
<code>${humanizeKind(group.kind)}</code>
|
|
||||||
</header>
|
|
||||||
<p><code>${escapeHtml(group.target)}</code></p>
|
|
||||||
<p>${escapeHtml(group.reason)}</p>
|
|
||||||
<p class="storage-audit__recommendation">${escapeHtml(group.recommendation)}</p>
|
|
||||||
</article>
|
|
||||||
`
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,19 +313,60 @@ function renderGroupedFindingList(groupedFindings, hasAnalysis, loading, showAll
|
|||||||
return `<section class="storage-audit__grouped">${sections.join("")}</section>`;
|
return `<section class="storage-audit__grouped">${sections.join("")}</section>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderGroupedSection(title, description, groups, renderGroup) {
|
function renderGroupedSection(title, description, content) {
|
||||||
const items = groups.map(renderGroup).join("");
|
|
||||||
return `
|
return `
|
||||||
<section class="storage-audit__group">
|
<section class="storage-audit__group">
|
||||||
<div class="storage-audit__group-header">
|
<div class="storage-audit__group-header">
|
||||||
<h3>${title}</h3>
|
<h3>${title}</h3>
|
||||||
<p>${description}</p>
|
<p>${description}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="storage-audit__list">${items}</div>
|
<div class="storage-audit__table-wrap">${content}</div>
|
||||||
</section>
|
</section>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderGroupedTable(groups, { includeOwner=false, includeReason=false, includeSources=false }={}) {
|
||||||
|
const headers = [
|
||||||
|
`<th>${localize("KSA.Table.Severity")}</th>`,
|
||||||
|
`<th>${localize("KSA.Field.Target")}</th>`,
|
||||||
|
`<th>${localize("KSA.Table.References")}</th>`
|
||||||
|
];
|
||||||
|
if (includeOwner) headers.push(`<th>${localize("KSA.Field.OwnerPackage")}</th>`);
|
||||||
|
if (includeReason) headers.push(`<th>${localize("KSA.Table.Note")}</th>`);
|
||||||
|
if (includeSources) headers.push(`<th>${localize("KSA.Field.Source")}</th>`);
|
||||||
|
|
||||||
|
const rows = groups.map(group => {
|
||||||
|
const cells = [
|
||||||
|
`<td><span class="storage-audit__severity storage-audit__severity--inline severity-${group.severity}">${severityLabel(group.severity)}</span></td>`,
|
||||||
|
`<td><code>${escapeHtml(group.target)}</code></td>`,
|
||||||
|
`<td>${group.count ?? ""}</td>`
|
||||||
|
];
|
||||||
|
if (includeOwner) cells.push(`<td><code>${escapeHtml(group.ownerLabel ?? "")}</code></td>`);
|
||||||
|
if (includeReason) {
|
||||||
|
const note = group.targetKind === "wildcard"
|
||||||
|
? `${group.shortReason ?? group.reason ?? ""} ${localize("KSA.Finding.WildcardNoMatch")}`
|
||||||
|
: (group.shortReason ?? group.reason ?? "");
|
||||||
|
cells.push(`<td>${escapeHtml(note.trim())}</td>`);
|
||||||
|
}
|
||||||
|
if (includeSources) {
|
||||||
|
cells.push(`<td>${renderGroupedSourcesCell(group.sources ?? [])}</td>`);
|
||||||
|
}
|
||||||
|
return `<tr>${cells.join("")}</tr>`;
|
||||||
|
}).join("");
|
||||||
|
|
||||||
|
return `
|
||||||
|
<table class="storage-audit__table">
|
||||||
|
<thead><tr>${headers.join("")}</tr></thead>
|
||||||
|
<tbody>${rows}</tbody>
|
||||||
|
</table>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderGroupedSourcesCell(sources) {
|
||||||
|
if (!sources.length) return "";
|
||||||
|
return `<div class="storage-audit__source-list">${sources.map(source => `<div>${source.renderedSource ?? renderPlainSourceLabel(source)}</div>`).join("")}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
function renderFindingList(findings, hasAnalysis, loading, showAll, showRaw) {
|
function renderFindingList(findings, hasAnalysis, loading, showAll, showRaw) {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return `<section class="storage-audit__list"><p>${localize("KSA.Section.Running")}</p></section>`;
|
return `<section class="storage-audit__list"><p>${localize("KSA.Section.Running")}</p></section>`;
|
||||||
@@ -391,12 +404,6 @@ function renderFindingList(findings, hasAnalysis, loading, showAll, showRaw) {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSampleSources(sources) {
|
|
||||||
if (!sources.length) return "";
|
|
||||||
const rows = sources.map(source => `<li>${source.renderedSource ?? renderPlainSourceLabel(source)}</li>`).join("");
|
|
||||||
return `<div class="storage-audit__samples"><span>${localize("KSA.Section.Samples")}</span><ul>${rows}</ul></div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function groupFindings(findings) {
|
function groupFindings(findings) {
|
||||||
return {
|
return {
|
||||||
brokenReferences: groupByTarget(findings.filter(f => f.kind === "broken-reference")),
|
brokenReferences: groupByTarget(findings.filter(f => f.kind === "broken-reference")),
|
||||||
|
|||||||
@@ -35,6 +35,11 @@
|
|||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.storage-audit__table-wrap {
|
||||||
|
padding: 0 1.1rem 1.1rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.storage-audit__progress {
|
.storage-audit__progress {
|
||||||
padding: 1rem 1.1rem;
|
padding: 1rem 1.1rem;
|
||||||
}
|
}
|
||||||
@@ -194,6 +199,42 @@
|
|||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.storage-audit__table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.storage-audit__table th,
|
||||||
|
.storage-audit__table td {
|
||||||
|
padding: 0.55rem 0.5rem;
|
||||||
|
vertical-align: top;
|
||||||
|
text-align: left;
|
||||||
|
border-top: 1px solid color-mix(in srgb, currentColor 10%, transparent);
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.storage-audit__table thead th {
|
||||||
|
border-top: 0;
|
||||||
|
opacity: 0.75;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.storage-audit__table td:first-child,
|
||||||
|
.storage-audit__table th:first-child {
|
||||||
|
width: 7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.storage-audit__table td:nth-child(3),
|
||||||
|
.storage-audit__table th:nth-child(3) {
|
||||||
|
width: 7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.storage-audit__source-list {
|
||||||
|
display: grid;
|
||||||
|
gap: 0.35rem;
|
||||||
|
}
|
||||||
|
|
||||||
.storage-audit__list--raw h3 {
|
.storage-audit__list--raw h3 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
@@ -223,6 +264,10 @@
|
|||||||
letter-spacing: 0.04em;
|
letter-spacing: 0.04em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.storage-audit__severity--inline {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.severity-high .storage-audit__severity {
|
.severity-high .storage-audit__severity {
|
||||||
background: color-mix(in srgb, #b03e29 80%, transparent);
|
background: color-mix(in srgb, #b03e29 80%, transparent);
|
||||||
color: white;
|
color: white;
|
||||||
|
|||||||
Reference in New Issue
Block a user