core/validators/manifest.prose.validator.ts
core/validators/manifest.prose.validator.ts is a file in GovLab Docs. 121 lines of code and 17 definitions.
import type {
DeclaredDocFinding,
DeclaredGovernContext,
DiscoveredModule,
ManifestFinding,
ProseFinding,
} from "#types/readme.types";
import { LEAD_HEADING, hardcodedCount, historySmell } from "#configuration/strings/governance.strings";
import { cleanTarget, unquote } from "#core/normalizers/reference.normalizer";
import { dirname, resolve } from "node:path";
import { hostCoupling, missingTarget, symbolDrift } from "#configuration/strings/reference.strings";
import { renderFieldFragment, renderRenderable } from "#core/formatters/markdown.formatter";
import type { DocumentDecl } from "#types/document.types";
import { bannedLanguage } from "#core/analyzers/vocabulary.analyzer";
import { conventionHits } from "#core/analyzers/markdown.analyzer";
import { declaredDocLocation } from "#core/resolvers/location.resolver";
import { hardcodedCounts } from "#core/analyzers/text.analyzer";
import { isExternalTarget } from "#core/predicates/reference.predicate";
import { pathReferences } from "#core/parsers/location.parser";
import { symbolDriftIn } from "#core/analyzers/drift.analyzer";
import { targetExists } from "#core/resolvers/source.resolver";
export const brokenPathsIn = function brokenPathsIn(
fragment: string,
moduleDir: string,
consumerRoot: string,
): string[] {
return pathReferences(fragment)
.map((ref) => cleanTarget(ref.path))
.filter((target) => !isExternalTarget(target) && !targetExists(target, moduleDir, consumerRoot));
};
export const hostCouplingIn = function hostCouplingIn(fragment: string, hostTokens: readonly string[]): string[] {
return pathReferences(fragment)
.map((ref) => unquote(ref.path))
.filter((target) => hostTokens.some((token) => target.startsWith(token)));
};
const textFindings = function textFindings(fragment: string): ProseFinding[] {
return [
...bannedLanguage(fragment).map((hit) => ({ axis: "history-smell", detail: historySmell(hit.term) })),
...conventionHits(fragment).map((hit) => ({ axis: hit.code, detail: hit.token })),
];
};
const pathFindings = function pathFindings(fragment: string, dir: string, consumerRoot: string): ProseFinding[] {
return [
...brokenPathsIn(fragment, dir, consumerRoot).map((target) => ({
axis: "broken-path",
detail: missingTarget(target),
})),
...symbolDriftIn(fragment, dir, consumerRoot).map((detail) => ({
axis: "symbol-drift",
detail: symbolDrift(detail),
})),
];
};
export const governManifest = function governManifest(
module: DiscoveredModule,
consumerRoot: string,
hostTokens: readonly string[],
): ManifestFinding[] {
const { docs } = module.manifest;
if (!docs || typeof docs !== "object") {
return [];
}
return Object.entries(docs).flatMap(([key, value]) => {
const fragment = renderFieldFragment(key, value);
const coupled = hostCouplingIn(fragment, hostTokens).map((target) => ({
axis: "host-coupling",
detail: hostCoupling(target),
}));
return [...textFindings(fragment), ...pathFindings(fragment, module.dir, consumerRoot), ...coupled].map(
(finding): ManifestFinding => ({ ...finding, field: key }),
);
});
};
const sectionFindings = function sectionFindings(
docDir: string,
consumerRoot: string,
content: unknown,
): ProseFinding[] {
const fragment = renderRenderable(content);
return [
...textFindings(fragment),
...pathFindings(fragment, docDir, consumerRoot),
...hardcodedCounts(fragment).map((count) => ({ axis: "magic-number", detail: hardcodedCount(count) })),
];
};
const safeDocLocation = function safeDocLocation(doc: DocumentDecl, context: DeclaredGovernContext): string | null {
try {
return declaredDocLocation(doc, context.registries, context.options);
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
return null;
}
};
const docDirOf = function docDirOf(doc: DocumentDecl, context: DeclaredGovernContext): string | null {
const location = safeDocLocation(doc, context);
return location === null ? null : dirname(resolve(context.consumerRoot, location));
};
const docFindings = function docFindings(doc: DocumentDecl, context: DeclaredGovernContext): DeclaredDocFinding[] {
const docDir = Array.isArray(doc.body) ? docDirOf(doc, context) : null;
if (docDir === null) {
return [];
}
const lead =
typeof doc.lead === "string" || Array.isArray(doc.lead) ? [{ content: doc.lead, heading: LEAD_HEADING }] : [];
return [...lead, ...doc.body].flatMap((section) =>
sectionFindings(docDir, context.consumerRoot, section.content).map((finding): DeclaredDocFinding => ({
...finding,
doc: doc.name,
heading: section.heading,
})),
);
};
export const governDeclaredDocs = function governDeclaredDocs(
module: DiscoveredModule,
context: DeclaredGovernContext,
): DeclaredDocFinding[] {
const { documents } = module.manifest;
return Array.isArray(documents) ? documents.flatMap((doc) => docFindings(doc, context)) : [];
};