@greenarmor/ges-scoring-engine 0.5.0 → 0.5.2
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/dist/index.d.ts +2 -1
- package/dist/index.js +63 -6
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -14,4 +14,5 @@ export declare function generateScoreFile(controls: Control[], frameworks: Frame
|
|
|
14
14
|
export declare function formatScoreOutput(score: ScoreFile): string;
|
|
15
15
|
export { SEVERITY_WEIGHTS, STATUS_CREDIT, SEVERITY_PENALTY, computeGrade };
|
|
16
16
|
export declare function generateBadgeSvg(score: ScoreFile): string;
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function generateScoreExplainer(score: ScoreFile): string;
|
|
18
|
+
export declare function injectBadgeIntoReadme(readmeContent: string, badgeSvgPath: string, scoreExplainer?: string): string;
|
package/dist/index.js
CHANGED
|
@@ -260,17 +260,74 @@ export function generateBadgeSvg(score) {
|
|
|
260
260
|
</g>
|
|
261
261
|
</svg>`;
|
|
262
262
|
}
|
|
263
|
-
export function
|
|
263
|
+
export function generateScoreExplainer(score) {
|
|
264
|
+
const lines = [];
|
|
265
|
+
const indent = "> ";
|
|
266
|
+
lines.push(`${indent}**GESF Compliance Score: ${score.overall}% (${score.overall_grade})**`);
|
|
267
|
+
lines.push(">");
|
|
268
|
+
lines.push(`${indent}| Framework | Score | Grade | Controls |`);
|
|
269
|
+
lines.push(`${indent}|-----------|-------|-------|----------|`);
|
|
270
|
+
for (const [fw, data] of Object.entries(score.frameworks)) {
|
|
271
|
+
const passed = data.passed_controls;
|
|
272
|
+
const total = data.total_controls;
|
|
273
|
+
lines.push(`${indent}| ${fw} | ${data.score}% | ${data.grade} | ${passed}/${total} passed |`);
|
|
274
|
+
}
|
|
275
|
+
if (score.audit_impact) {
|
|
276
|
+
const ai = score.audit_impact;
|
|
277
|
+
lines.push(">");
|
|
278
|
+
const parts = [];
|
|
279
|
+
if (ai.critical_findings > 0)
|
|
280
|
+
parts.push(`${ai.critical_findings} critical`);
|
|
281
|
+
if (ai.high_findings > 0)
|
|
282
|
+
parts.push(`${ai.high_findings} high`);
|
|
283
|
+
if (ai.medium_findings > 0)
|
|
284
|
+
parts.push(`${ai.medium_findings} medium`);
|
|
285
|
+
if (ai.low_findings > 0)
|
|
286
|
+
parts.push(`${ai.low_findings} low`);
|
|
287
|
+
if (parts.length > 0) {
|
|
288
|
+
lines.push(`${indent}Audit findings: ${parts.join(", ")} (score deduction: -${ai.total_deduction}%)`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
lines.push(">");
|
|
292
|
+
lines.push(`${indent}_(Last evaluated: ${score.evaluated_at.split("T")[0]})_`);
|
|
293
|
+
return lines.join("\n");
|
|
294
|
+
}
|
|
295
|
+
const EXPLAINER_START = "<!-- GESF-SCORE-START -->";
|
|
296
|
+
const EXPLAINER_END = "<!-- GESF-SCORE-END -->";
|
|
297
|
+
export function injectBadgeIntoReadme(readmeContent, badgeSvgPath, scoreExplainer) {
|
|
264
298
|
const badgeLine = ``;
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
299
|
+
const explainerBlock = scoreExplainer
|
|
300
|
+
? `\n${EXPLAINER_START}\n${scoreExplainer}\n${EXPLAINER_END}`
|
|
301
|
+
: "";
|
|
302
|
+
const existingBadge = /!\[GESF Compliance\]\([^)]*\)/;
|
|
303
|
+
const hasExistingExplainer = readmeContent.includes(EXPLAINER_START) && readmeContent.includes(EXPLAINER_END);
|
|
304
|
+
if (hasExistingExplainer) {
|
|
305
|
+
let updated = readmeContent;
|
|
306
|
+
if (existingBadge.test(updated)) {
|
|
307
|
+
updated = updated.replace(existingBadge, badgeLine);
|
|
308
|
+
}
|
|
309
|
+
const explainerRegex = new RegExp(EXPLAINER_START.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") +
|
|
310
|
+
"[\\s\\S]*?" +
|
|
311
|
+
EXPLAINER_END.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
|
312
|
+
updated = updated.replace(explainerRegex, `${EXPLAINER_START}\n${scoreExplainer || ""}\n${EXPLAINER_END}\n`);
|
|
313
|
+
return updated;
|
|
314
|
+
}
|
|
315
|
+
if (existingBadge.test(readmeContent)) {
|
|
316
|
+
if (scoreExplainer) {
|
|
317
|
+
const badgeIdx = readmeContent.indexOf("![GESF Compliance]");
|
|
318
|
+
const lineEnd = readmeContent.indexOf("\n", badgeIdx);
|
|
319
|
+
const afterBadge = lineEnd !== -1 ? lineEnd : readmeContent.length;
|
|
320
|
+
return readmeContent.slice(0, badgeIdx) + badgeLine +
|
|
321
|
+
"\n" + EXPLAINER_START + "\n" + scoreExplainer + "\n" + EXPLAINER_END + "\n\n" +
|
|
322
|
+
readmeContent.slice(afterBadge + 1);
|
|
323
|
+
}
|
|
324
|
+
return readmeContent.replace(existingBadge, badgeLine);
|
|
268
325
|
}
|
|
269
326
|
const headingMatch = readmeContent.match(/^#\s+.+$/m);
|
|
270
327
|
if (headingMatch && headingMatch.index !== undefined) {
|
|
271
328
|
const afterHeading = headingMatch.index + headingMatch[0].length;
|
|
272
|
-
const insertion = `\n\n${badgeLine}`;
|
|
329
|
+
const insertion = `\n\n${badgeLine}${explainerBlock}\n`;
|
|
273
330
|
return readmeContent.slice(0, afterHeading) + insertion + readmeContent.slice(afterHeading);
|
|
274
331
|
}
|
|
275
|
-
return badgeLine + "\n\n" + readmeContent;
|
|
332
|
+
return badgeLine + explainerBlock + "\n\n" + readmeContent;
|
|
276
333
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@greenarmor/ges-scoring-engine",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "GESF Scoring Engine - Compliance scoring across frameworks",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@greenarmor/ges-core": "0.5.
|
|
15
|
+
"@greenarmor/ges-core": "0.5.2"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/node": "^22.0.0",
|