@hyperframes/lint 0.9.13 → 0.9.15

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.js CHANGED
@@ -6486,7 +6486,11 @@ var textureRules = [
6486
6486
 
6487
6487
  // src/rules/fonts.ts
6488
6488
  import postcss3 from "postcss";
6489
- import { FONT_ALIAS_KEYS, resolveAliasDisplayName } from "@hyperframes/parsers/composition";
6489
+ import {
6490
+ FONT_ALIAS_KEYS,
6491
+ parseFontShorthand,
6492
+ resolveAliasDisplayName
6493
+ } from "@hyperframes/parsers/composition";
6490
6494
  var GENERIC_FAMILIES = /* @__PURE__ */ new Set([
6491
6495
  "serif",
6492
6496
  "sans-serif",
@@ -6569,14 +6573,20 @@ function resolveUsedFontNames(value, properties, resolving = /* @__PURE__ */ new
6569
6573
  return resolveUsedFontNames(referenced, properties, new Set(resolving).add(property));
6570
6574
  });
6571
6575
  }
6576
+ function usedFamilyList(decl) {
6577
+ if (isFontFaceDeclaration(decl)) return "";
6578
+ if (decl.prop.toLowerCase() !== "font") return decl.value;
6579
+ const shorthand = parseFontShorthand(decl.value);
6580
+ return shorthand.certain ? shorthand.families : "";
6581
+ }
6582
+ var FONT_FAMILY_PROPS = /^font(?:-family)?$/i;
6572
6583
  function extractUsedFontFamilies(styles) {
6573
6584
  const used = [];
6574
6585
  const seen = /* @__PURE__ */ new Set();
6575
6586
  const properties = collectFontCustomProperties(styles);
6576
6587
  for (const style of styles) {
6577
- parseFontCss(style.content)?.walkDecls(/^font-family$/i, (decl) => {
6578
- if (isFontFaceDeclaration(decl)) return;
6579
- for (const name of resolveUsedFontNames(decl.value, properties)) {
6588
+ parseFontCss(style.content)?.walkDecls(FONT_FAMILY_PROPS, (decl) => {
6589
+ for (const name of resolveUsedFontNames(usedFamilyList(decl), properties)) {
6580
6590
  if (!GENERIC_FAMILIES.has(name) && !seen.has(name)) {
6581
6591
  seen.add(name);
6582
6592
  used.push(name);
@@ -6678,9 +6688,33 @@ var fontRules = [
6678
6688
  code: "font_family_without_font_face",
6679
6689
  severity: "error",
6680
6690
  message: `Font ${undeclared.length === 1 ? "family" : "families"} used without @font-face declaration: ${undeclared.join(", ")}. These are not in the auto-resolved font list, so the renderer cannot supply them automatically. Text will fall back to a generic font, producing incorrect typography in the video.`,
6681
- fixHint: "Add @font-face { font-family: '...'; src: url('capture/assets/fonts/...woff2'); } for each font family, pointing to the captured .woff2 files. For an OS-bundled system font (e.g. Hiragino Sans, Microsoft YaHei) that has no downloadable file, use src: local('Exact Font Name') instead. The declaration alone satisfies this check without needing a font file."
6691
+ fixHint: "Add @font-face { font-family: '...'; src: url('capture/assets/fonts/...woff2'); } for each font family, pointing to the captured .woff2 files, or switch to a Google Fonts family. An OS font such as PingFang SC or Hiragino Sans renders locally from the installed copy, but a cloud render has no copy and refuses it."
6682
6692
  });
6683
6693
  return findings;
6694
+ },
6695
+ ({ styles, rawSource, options, locate }) => {
6696
+ if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];
6697
+ const findings = [];
6698
+ for (const style of styles) {
6699
+ parseFontCss(style.content)?.walkAtRules(/^font-face$/i, (rule) => {
6700
+ let family = null;
6701
+ let sources = "";
6702
+ rule.walkDecls((decl) => {
6703
+ const prop = decl.prop.toLowerCase();
6704
+ if (prop === "font-family") family = normalizeUsedFontName(decl.value);
6705
+ else if (prop === "src") sources += ` ${decl.value}`;
6706
+ });
6707
+ if (!family || !/\blocal\s*\(/i.test(sources) || /\burl\s*\(/i.test(sources)) return;
6708
+ findings.push({
6709
+ ...locate(style, rule.source?.start?.offset),
6710
+ code: "font_face_local_only",
6711
+ severity: "warning",
6712
+ message: `@font-face '${family}' only names a font installed on this machine (src: local()). A local render uses the installed copy; a cloud render or another machine has none and falls back to a different font.`,
6713
+ fixHint: "Add a url() source to the font file (.woff2) inside the project, or use a Google Fonts family, so every render draws the same glyphs."
6714
+ });
6715
+ });
6716
+ }
6717
+ return findings;
6684
6718
  }
6685
6719
  ];
6686
6720
  function uniqueFontLocation(styles, families, locate) {
@@ -6688,10 +6722,9 @@ function uniqueFontLocation(styles, families, locate) {
6688
6722
  const properties = collectFontCustomProperties(styles);
6689
6723
  for (const style of styles) {
6690
6724
  try {
6691
- postcss3.parse(style.content).walkDecls(/^font-family$/i, (decl) => {
6692
- if (isFontFaceDeclaration(decl)) return;
6693
- if (!resolveUsedFontNames(decl.value, properties).some((name) => families.includes(name)))
6694
- return;
6725
+ postcss3.parse(style.content).walkDecls(FONT_FAMILY_PROPS, (decl) => {
6726
+ const named = resolveUsedFontNames(usedFamilyList(decl), properties);
6727
+ if (!named.some((name) => families.includes(name))) return;
6695
6728
  locations.push(locate(style, decl.source?.start?.offset));
6696
6729
  });
6697
6730
  } catch {
package/dist/index.js CHANGED
@@ -6492,7 +6492,11 @@ var textureRules = [
6492
6492
 
6493
6493
  // src/rules/fonts.ts
6494
6494
  import postcss3 from "postcss";
6495
- import { FONT_ALIAS_KEYS, resolveAliasDisplayName } from "@hyperframes/parsers/composition";
6495
+ import {
6496
+ FONT_ALIAS_KEYS,
6497
+ parseFontShorthand,
6498
+ resolveAliasDisplayName
6499
+ } from "@hyperframes/parsers/composition";
6496
6500
  var GENERIC_FAMILIES = /* @__PURE__ */ new Set([
6497
6501
  "serif",
6498
6502
  "sans-serif",
@@ -6575,14 +6579,20 @@ function resolveUsedFontNames(value, properties, resolving = /* @__PURE__ */ new
6575
6579
  return resolveUsedFontNames(referenced, properties, new Set(resolving).add(property));
6576
6580
  });
6577
6581
  }
6582
+ function usedFamilyList(decl) {
6583
+ if (isFontFaceDeclaration(decl)) return "";
6584
+ if (decl.prop.toLowerCase() !== "font") return decl.value;
6585
+ const shorthand = parseFontShorthand(decl.value);
6586
+ return shorthand.certain ? shorthand.families : "";
6587
+ }
6588
+ var FONT_FAMILY_PROPS = /^font(?:-family)?$/i;
6578
6589
  function extractUsedFontFamilies(styles) {
6579
6590
  const used = [];
6580
6591
  const seen = /* @__PURE__ */ new Set();
6581
6592
  const properties = collectFontCustomProperties(styles);
6582
6593
  for (const style of styles) {
6583
- parseFontCss(style.content)?.walkDecls(/^font-family$/i, (decl) => {
6584
- if (isFontFaceDeclaration(decl)) return;
6585
- for (const name of resolveUsedFontNames(decl.value, properties)) {
6594
+ parseFontCss(style.content)?.walkDecls(FONT_FAMILY_PROPS, (decl) => {
6595
+ for (const name of resolveUsedFontNames(usedFamilyList(decl), properties)) {
6586
6596
  if (!GENERIC_FAMILIES.has(name) && !seen.has(name)) {
6587
6597
  seen.add(name);
6588
6598
  used.push(name);
@@ -6684,9 +6694,33 @@ var fontRules = [
6684
6694
  code: "font_family_without_font_face",
6685
6695
  severity: "error",
6686
6696
  message: `Font ${undeclared.length === 1 ? "family" : "families"} used without @font-face declaration: ${undeclared.join(", ")}. These are not in the auto-resolved font list, so the renderer cannot supply them automatically. Text will fall back to a generic font, producing incorrect typography in the video.`,
6687
- fixHint: "Add @font-face { font-family: '...'; src: url('capture/assets/fonts/...woff2'); } for each font family, pointing to the captured .woff2 files. For an OS-bundled system font (e.g. Hiragino Sans, Microsoft YaHei) that has no downloadable file, use src: local('Exact Font Name') instead. The declaration alone satisfies this check without needing a font file."
6697
+ fixHint: "Add @font-face { font-family: '...'; src: url('capture/assets/fonts/...woff2'); } for each font family, pointing to the captured .woff2 files, or switch to a Google Fonts family. An OS font such as PingFang SC or Hiragino Sans renders locally from the installed copy, but a cloud render has no copy and refuses it."
6688
6698
  });
6689
6699
  return findings;
6700
+ },
6701
+ ({ styles, rawSource, options, locate }) => {
6702
+ if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];
6703
+ const findings = [];
6704
+ for (const style of styles) {
6705
+ parseFontCss(style.content)?.walkAtRules(/^font-face$/i, (rule) => {
6706
+ let family = null;
6707
+ let sources = "";
6708
+ rule.walkDecls((decl) => {
6709
+ const prop = decl.prop.toLowerCase();
6710
+ if (prop === "font-family") family = normalizeUsedFontName(decl.value);
6711
+ else if (prop === "src") sources += ` ${decl.value}`;
6712
+ });
6713
+ if (!family || !/\blocal\s*\(/i.test(sources) || /\burl\s*\(/i.test(sources)) return;
6714
+ findings.push({
6715
+ ...locate(style, rule.source?.start?.offset),
6716
+ code: "font_face_local_only",
6717
+ severity: "warning",
6718
+ message: `@font-face '${family}' only names a font installed on this machine (src: local()). A local render uses the installed copy; a cloud render or another machine has none and falls back to a different font.`,
6719
+ fixHint: "Add a url() source to the font file (.woff2) inside the project, or use a Google Fonts family, so every render draws the same glyphs."
6720
+ });
6721
+ });
6722
+ }
6723
+ return findings;
6690
6724
  }
6691
6725
  ];
6692
6726
  function uniqueFontLocation(styles, families, locate) {
@@ -6694,10 +6728,9 @@ function uniqueFontLocation(styles, families, locate) {
6694
6728
  const properties = collectFontCustomProperties(styles);
6695
6729
  for (const style of styles) {
6696
6730
  try {
6697
- postcss3.parse(style.content).walkDecls(/^font-family$/i, (decl) => {
6698
- if (isFontFaceDeclaration(decl)) return;
6699
- if (!resolveUsedFontNames(decl.value, properties).some((name) => families.includes(name)))
6700
- return;
6731
+ postcss3.parse(style.content).walkDecls(FONT_FAMILY_PROPS, (decl) => {
6732
+ const named = resolveUsedFontNames(usedFamilyList(decl), properties);
6733
+ if (!named.some((name) => families.includes(name))) return;
6701
6734
  locations.push(locate(style, decl.source?.start?.offset));
6702
6735
  });
6703
6736
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/lint",
3
- "version": "0.9.13",
3
+ "version": "0.9.15",
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.9.13"
38
+ "@hyperframes/parsers": "0.9.15"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/node": "^25.0.10",