@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 +42 -9
- package/dist/index.js +42 -9
- package/package.json +2 -2
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 {
|
|
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(
|
|
6578
|
-
|
|
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
|
|
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(
|
|
6692
|
-
|
|
6693
|
-
if (!
|
|
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 {
|
|
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(
|
|
6584
|
-
|
|
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
|
|
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(
|
|
6698
|
-
|
|
6699
|
-
if (!
|
|
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.
|
|
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.
|
|
38
|
+
"@hyperframes/parsers": "0.9.15"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^25.0.10",
|