MCPcopy Create free account
hub / github.com/heygen-com/hyperframes / lintMissingLocalAsset

Function lintMissingLocalAsset

packages/lint/src/project.ts:338–392  ·  view source on GitHub ↗
(
  projectDir: string,
  htmlSources: HtmlSource[],
)

Source from the content-addressed store, hash-verified

336
337// fallow-ignore-next-line complexity
338function lintMissingLocalAsset(
339 projectDir: string,
340 htmlSources: HtmlSource[],
341): HyperframeLintFinding[] {
342 const findings: HyperframeLintFinding[] = [];
343
344 const localAssetSrcRe = /<(video|img|source)\b[^>]*\bsrc\s*=\s*["']([^"']+)["'][^>]*>/gi;
345
346 const missingByTag = new Map<string, Map<string, string>>();
347
348 for (const { html, compSrcPath } of htmlSources) {
349 const scannable = maskNonScannableRanges(html);
350 const re = new RegExp(localAssetSrcRe.source, localAssetSrcRe.flags);
351 let match: RegExpExecArray | null;
352 while ((match = re.exec(scannable)) !== null) {
353 const tagName = (match[1] ?? "").toLowerCase();
354 const rawSrc = match[2] ?? "";
355 const src = cleanAssetUrl(rawSrc);
356 if (!src) continue;
357 if (isRemoteOrInlineUrl(src)) continue;
358 if (/^__[A-Z_]+__$/.test(src)) continue;
359 const rootRelative = compSrcPath ? rewriteAssetPath(compSrcPath, src) : src;
360 const resolvedAsset = resolveExistingLocalAsset(projectDir, rootRelative);
361 if (resolvedAsset) continue;
362
363 const resolvedKey = resolve(projectDir, rootRelative);
364 let bucket = missingByTag.get(tagName);
365 if (!bucket) {
366 bucket = new Map<string, string>();
367 missingByTag.set(tagName, bucket);
368 }
369 if (!bucket.has(resolvedKey)) bucket.set(resolvedKey, src);
370 }
371 }
372
373 for (const [tagName, byResolved] of missingByTag) {
374 const unique = [...byResolved.values()];
375 findings.push({
376 code: "missing_local_asset",
377 severity: "error",
378 message:
379 `<${tagName}> element references local file(s) not found in the project: ${unique.join(", ")}. ` +
380 "The renderer will silently skip these and produce a video with missing visuals.",
381 fixHint:
382 unique.length === 1
383 ? `Add "${unique[0]}" to the project directory, or update the src attribute to point to an existing file. ` +
384 "Common cause: captured asset filenames are unreliable (heygen-logo.svg often contains Google, nvidia-logo.svg may contain Autodesk, etc.). " +
385 "Open the contact sheets and verify the file actually exists at this path before referencing it."
386 : "Add the missing files to the project directory, or update the src attributes to point to existing files. " +
387 "Captured asset filenames are unreliable — verify against capture/contact-sheets/ and capture/extracted/asset-descriptions.md.",
388 });
389 }
390
391 return findings;
392}
393
394function lintTextureMaskAssetNotFound(
395 projectDir: string,

Callers 1

lintProjectFunction · 0.85

Calls 8

maskNonScannableRangesFunction · 0.85
cleanAssetUrlFunction · 0.85
isRemoteOrInlineUrlFunction · 0.85
rewriteAssetPathFunction · 0.85
resolveFunction · 0.85
getMethod · 0.80
setMethod · 0.65

Tested by

no test coverage detected