@hyperframes/lint 0.8.222 → 0.8.223

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/browser.d.ts CHANGED
@@ -43,6 +43,13 @@ type HyperframeLinterOptions = {
43
43
  file?: string;
44
44
  rootRelativePath?: string;
45
45
  }>;
46
+ externalScripts?: Array<{
47
+ src: string;
48
+ attrs: string;
49
+ content: string;
50
+ file: string;
51
+ rootRelativePath: string;
52
+ }>;
46
53
  /**
47
54
  * Set to `true` when linting compositions destined for distributed / Lambda
48
55
  * rendering, where system-font capture (`allowSystemFontCapture`) is
package/dist/browser.js CHANGED
@@ -786,7 +786,17 @@ function buildLintContext(html, options = {}) {
786
786
  rootRelativePath: style.rootRelativePath
787
787
  }))
788
788
  ];
789
- const scripts = structure.scripts;
789
+ const scripts = [
790
+ ...structure.scripts,
791
+ ...(options.externalScripts ?? []).map((script) => ({
792
+ attrs: script.attrs,
793
+ content: script.content,
794
+ raw: script.content,
795
+ index: -1,
796
+ file: script.file,
797
+ rootRelativePath: script.rootRelativePath
798
+ }))
799
+ ];
790
800
  const compositionIds = collectCompositionIds(tags);
791
801
  const rootTag = findRootTag(source, tags);
792
802
  const rootCompositionId = readDecodedAttr(rootTag?.raw || "", "data-composition-id");
@@ -1389,7 +1399,10 @@ var coreRules = [
1389
1399
  }
1390
1400
  if (/(?:^|\s)data-no-timeline(?=[\s=/]|$)/i.test(rootTag?.attrs || "")) return [];
1391
1401
  const findings = [];
1392
- if (!TIMELINE_REGISTRY_INIT_PATTERN.test(source) && !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source) && !TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN.test(source)) {
1402
+ const registered = [source, ...(options.externalScripts ?? []).map((script) => script.content)];
1403
+ if (!registered.some(
1404
+ (text) => TIMELINE_REGISTRY_INIT_PATTERN.test(text) || TIMELINE_REGISTRY_ASSIGN_PATTERN.test(text) || TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN.test(text)
1405
+ )) {
1393
1406
  findings.push({
1394
1407
  code: "missing_timeline_registry",
1395
1408
  severity: "error",
@@ -1560,9 +1573,9 @@ var coreRules = [
1560
1573
  ({ scripts, locate }) => {
1561
1574
  const findings = [];
1562
1575
  for (const script of scripts) {
1563
- const type = readDecodedAttr(script.raw, "type")?.trim().toLowerCase() ?? "";
1564
- if (readDecodedAttr(script.raw, "src") !== null || SCRIPT_SYNTAX_EXEMPT_TYPES.has(type))
1565
- continue;
1576
+ const tag = `<script ${script.attrs}>`;
1577
+ const type = readDecodedAttr(tag, "type")?.trim().toLowerCase() ?? "";
1578
+ if (readDecodedAttr(tag, "src") !== null || SCRIPT_SYNTAX_EXEMPT_TYPES.has(type)) continue;
1566
1579
  const syntaxError = getInlineScriptSyntaxError(script.content);
1567
1580
  if (!syntaxError) continue;
1568
1581
  findings.push({
package/dist/index.d.ts CHANGED
@@ -43,6 +43,13 @@ type HyperframeLinterOptions = {
43
43
  file?: string;
44
44
  rootRelativePath?: string;
45
45
  }>;
46
+ externalScripts?: Array<{
47
+ src: string;
48
+ attrs: string;
49
+ content: string;
50
+ file: string;
51
+ rootRelativePath: string;
52
+ }>;
46
53
  /**
47
54
  * Set to `true` when linting compositions destined for distributed / Lambda
48
55
  * rendering, where system-font capture (`allowSystemFontCapture`) is
package/dist/index.js CHANGED
@@ -792,7 +792,17 @@ function buildLintContext(html, options = {}) {
792
792
  rootRelativePath: style.rootRelativePath
793
793
  }))
794
794
  ];
795
- const scripts = structure.scripts;
795
+ const scripts = [
796
+ ...structure.scripts,
797
+ ...(options.externalScripts ?? []).map((script) => ({
798
+ attrs: script.attrs,
799
+ content: script.content,
800
+ raw: script.content,
801
+ index: -1,
802
+ file: script.file,
803
+ rootRelativePath: script.rootRelativePath
804
+ }))
805
+ ];
796
806
  const compositionIds = collectCompositionIds(tags);
797
807
  const rootTag = findRootTag(source, tags);
798
808
  const rootCompositionId = readDecodedAttr(rootTag?.raw || "", "data-composition-id");
@@ -1395,7 +1405,10 @@ var coreRules = [
1395
1405
  }
1396
1406
  if (/(?:^|\s)data-no-timeline(?=[\s=/]|$)/i.test(rootTag?.attrs || "")) return [];
1397
1407
  const findings = [];
1398
- if (!TIMELINE_REGISTRY_INIT_PATTERN.test(source) && !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source) && !TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN.test(source)) {
1408
+ const registered = [source, ...(options.externalScripts ?? []).map((script) => script.content)];
1409
+ if (!registered.some(
1410
+ (text) => TIMELINE_REGISTRY_INIT_PATTERN.test(text) || TIMELINE_REGISTRY_ASSIGN_PATTERN.test(text) || TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN.test(text)
1411
+ )) {
1399
1412
  findings.push({
1400
1413
  code: "missing_timeline_registry",
1401
1414
  severity: "error",
@@ -1566,9 +1579,9 @@ var coreRules = [
1566
1579
  ({ scripts, locate }) => {
1567
1580
  const findings = [];
1568
1581
  for (const script of scripts) {
1569
- const type = readDecodedAttr(script.raw, "type")?.trim().toLowerCase() ?? "";
1570
- if (readDecodedAttr(script.raw, "src") !== null || SCRIPT_SYNTAX_EXEMPT_TYPES.has(type))
1571
- continue;
1582
+ const tag = `<script ${script.attrs}>`;
1583
+ const type = readDecodedAttr(tag, "type")?.trim().toLowerCase() ?? "";
1584
+ if (readDecodedAttr(tag, "src") !== null || SCRIPT_SYNTAX_EXEMPT_TYPES.has(type)) continue;
1572
1585
  const syntaxError = getInlineScriptSyntaxError(script.content);
1573
1586
  if (!syntaxError) continue;
1574
1587
  findings.push({
@@ -7492,6 +7505,30 @@ function collectExternalStyles(projectDir, html, compSrcPath) {
7492
7505
  }
7493
7506
  return styles;
7494
7507
  }
7508
+ var MAX_EXTERNAL_SCRIPT_BYTES = 1e6;
7509
+ function collectExternalScripts(projectDir, html, compSrcPath) {
7510
+ const scripts = [];
7511
+ const { document } = parseHTML3(html);
7512
+ for (const element of querySelectorAllIncludingTemplates(document, "script[src]")) {
7513
+ const src = element.getAttribute("src") ?? "";
7514
+ if (!isLocalStylesheetHref(src) || /\.min\.m?js(?:[?#]|$)/i.test(src)) continue;
7515
+ const path = src.split(/[?#]/)[0] ?? src;
7516
+ const besideFile = compSrcPath ? join3(dirname2(compSrcPath), path) : path;
7517
+ const script = resolveExistingLocalAsset3(projectDir, besideFile) ?? (compSrcPath && staysInsideProjectRoot(path) ? resolveExistingLocalAsset3(projectDir, path) : null);
7518
+ if (!script) continue;
7519
+ const read = readProjectFile2(script.resolved);
7520
+ if (read.kind !== "file" || read.text.length > MAX_EXTERNAL_SCRIPT_BYTES) continue;
7521
+ const attrs = Array.from(element.attributes).map(({ name, value }) => `${name}="${value.replace(/&/g, "&amp;").replace(/"/g, "&quot;")}"`).join(" ");
7522
+ scripts.push({
7523
+ src,
7524
+ attrs,
7525
+ content: read.text,
7526
+ file: join3(projectDir, script.rootRelativePath),
7527
+ rootRelativePath: script.rootRelativePath
7528
+ });
7529
+ }
7530
+ return scripts;
7531
+ }
7495
7532
  function collectCssSources(projectDir, html, compSrcPath) {
7496
7533
  const sources = [];
7497
7534
  const { document } = parseHTML3(html);
@@ -7582,7 +7619,8 @@ async function lintProject(projectDir, entryFile, hostOptions = {}) {
7582
7619
  filePath: indexPath,
7583
7620
  compSrcPath: rootFile,
7584
7621
  externalStyles: collectExternalStyles(projectDir, rootHtml, rootCompSrcPath),
7585
- projectFontFamilies
7622
+ projectFontFamilies,
7623
+ externalScripts: collectExternalScripts(projectDir, rootHtml, rootCompSrcPath)
7586
7624
  });
7587
7625
  results.push({ file: rootFile, result: rootResult, contentHash: contentDigest(rootHtml) });
7588
7626
  totalErrors += rootResult.errorCount;
@@ -7617,7 +7655,8 @@ async function lintProject(projectDir, entryFile, hostOptions = {}) {
7617
7655
  isSubComposition: true,
7618
7656
  compSrcPath,
7619
7657
  externalStyles: collectExternalStyles(projectDir, html, compSrcPath),
7620
- projectFontFamilies
7658
+ projectFontFamilies,
7659
+ externalScripts: collectExternalScripts(projectDir, html, compSrcPath)
7621
7660
  });
7622
7661
  results.push({
7623
7662
  file: `compositions/${file}`,
@@ -7900,6 +7939,7 @@ function lintLinkedStylesheetAssets(projectDir, htmlSources) {
7900
7939
  }
7901
7940
  return findings;
7902
7941
  }
7942
+ var PAGES_OPENED_BESIDE_INDEX = /* @__PURE__ */ new Set(["caption-skin.html", "podcast-lanes.html"]);
7903
7943
  function lintMultipleRootCompositions(projectDir) {
7904
7944
  const findings = [];
7905
7945
  try {
@@ -7908,7 +7948,7 @@ function lintMultipleRootCompositions(projectDir) {
7908
7948
  );
7909
7949
  const rootCompositions = [];
7910
7950
  for (const file of rootHtmlFiles) {
7911
- if (file === "caption-skin.html") continue;
7951
+ if (PAGES_OPENED_BESIDE_INDEX.has(file)) continue;
7912
7952
  const content = readFileSync(join3(projectDir, file), "utf-8");
7913
7953
  if (/data-composition-id/i.test(content)) {
7914
7954
  rootCompositions.push(file);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/lint",
3
- "version": "0.8.222",
3
+ "version": "0.8.223",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/heygen-com/hyperframes",
@@ -35,7 +35,7 @@
35
35
  "linkedom": "^0.18.12",
36
36
  "postcss": "^8.5.8",
37
37
  "postcss-selector-parser": "^7.1.4",
38
- "@hyperframes/parsers": "0.8.222"
38
+ "@hyperframes/parsers": "0.8.223"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/node": "^25.0.10",