mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-07 10:06:21 +00:00
* refactor: extract @hyperframes/lint package from core Moves all lint rules, hyperframeLinter, lintProject, and related types from packages/core/src/lint/ into a new standalone packages/lint package. Core keeps a thin re-export stub at @hyperframes/core/lint for backward compatibility. Consumer imports (cli lint command, producer hyperframeLint) are updated to import from @hyperframes/lint directly. Depends on @hyperframes/parsers (PR #1755). * fix: restore postcss-selector-parser in core (sourceMutation.ts still uses it) * fix(ci): add parsers+lint to Dockerfile and build before preview tests * chore: update bun.lock after restoring postcss-selector-parser dep * test(cli): update lintProject test for string-dir signature from @hyperframes/lint * refactor(core): single-source the lint engine in @hyperframes/lint Delete core's byte-identical copy of the lint rule engine and re-point staticGuard at @hyperframes/lint, so the render-time render-gate and the studio preview share one rule engine instead of two copies that could silently diverge. Back-compat preserved via the @hyperframes/core/lint stub. Addresses review feedback on the dual-copy footgun.
42 lines
1.4 KiB
TypeScript
42 lines
1.4 KiB
TypeScript
import { lintHyperframeHtml } from "@hyperframes/lint";
|
|
|
|
export type HyperframeStaticFailureReason =
|
|
| "missing_composition_id"
|
|
| "missing_composition_dimensions"
|
|
| "missing_timeline_registry"
|
|
| "invalid_script_syntax"
|
|
| "invalid_static_hyperframe_contract";
|
|
|
|
export type HyperframeStaticGuardResult = {
|
|
isValid: boolean;
|
|
missingKeys: string[];
|
|
failureReason: HyperframeStaticFailureReason | null;
|
|
};
|
|
|
|
export async function validateHyperframeHtmlContract(
|
|
html: string,
|
|
): Promise<HyperframeStaticGuardResult> {
|
|
const result = await lintHyperframeHtml(html);
|
|
const missingKeys = result.findings
|
|
.filter((finding) => finding.severity === "error")
|
|
.map((finding) => finding.message);
|
|
|
|
if (missingKeys.length === 0) {
|
|
return { isValid: true, missingKeys: [], failureReason: null };
|
|
}
|
|
|
|
const joined = missingKeys.join(" ").toLowerCase();
|
|
let failureReason: HyperframeStaticFailureReason = "invalid_static_hyperframe_contract";
|
|
if (joined.includes("data-composition-id")) {
|
|
failureReason = "missing_composition_id";
|
|
} else if (joined.includes("data-width") || joined.includes("data-height")) {
|
|
failureReason = "missing_composition_dimensions";
|
|
} else if (joined.includes("window.__timelines")) {
|
|
failureReason = "missing_timeline_registry";
|
|
} else if (joined.includes("script syntax")) {
|
|
failureReason = "invalid_script_syntax";
|
|
}
|
|
|
|
return { isValid: false, missingKeys, failureReason };
|
|
}
|