diff --git a/packages/core/src/lint/context.ts b/packages/core/src/lint/context.ts new file mode 100644 index 000000000..b0020ead9 --- /dev/null +++ b/packages/core/src/lint/context.ts @@ -0,0 +1,51 @@ +import type { HyperframeLintFinding, HyperframeLinterOptions } from "./types"; +import { + extractBlocks, + extractOpenTags, + findRootTag, + collectCompositionIds, + readAttr, + STYLE_BLOCK_PATTERN, + SCRIPT_BLOCK_PATTERN, +} from "./utils"; +import type { OpenTag, ExtractedBlock } from "./utils"; + +export type { OpenTag, ExtractedBlock }; + +export type LintContext = { + source: string; + tags: OpenTag[]; + styles: ExtractedBlock[]; + scripts: ExtractedBlock[]; + compositionIds: Set; + rootTag: OpenTag | null; + rootCompositionId: string | null; + options: HyperframeLinterOptions; +}; + +// Re-export for convenience so rule modules only need one import for the finding type +export type { HyperframeLintFinding }; + +export function buildLintContext(html: string, options: HyperframeLinterOptions = {}): LintContext { + let source = html || ""; + const templateMatch = source.match(/]*>([\s\S]*)<\/template>/i); + if (templateMatch?.[1]) source = templateMatch[1]; + + const tags = extractOpenTags(source); + const styles = extractBlocks(source, STYLE_BLOCK_PATTERN); + const scripts = extractBlocks(source, SCRIPT_BLOCK_PATTERN); + const compositionIds = collectCompositionIds(tags); + const rootTag = findRootTag(source); + const rootCompositionId = readAttr(rootTag?.raw || "", "data-composition-id"); + + return { + source, + tags, + styles, + scripts, + compositionIds, + rootTag, + rootCompositionId, + options, + }; +} diff --git a/packages/core/src/lint/hyperframeLinter.test.ts b/packages/core/src/lint/hyperframeLinter.test.ts index ec18fd93d..e8dbaf35d 100644 --- a/packages/core/src/lint/hyperframeLinter.test.ts +++ b/packages/core/src/lint/hyperframeLinter.test.ts @@ -115,6 +115,7 @@ describe("lintHyperframeHtml", () => { const html = `