@hyperframes/lint 0.9.19 → 0.9.21
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 +5 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +34 -16
- package/package.json +2 -2
package/dist/browser.js
CHANGED
|
@@ -1679,6 +1679,11 @@ var coreRules = [
|
|
|
1679
1679
|
label: "crypto.getRandomValues()",
|
|
1680
1680
|
hint: "Use a seeded PRNG (e.g. a simple mulberry32) so renders are deterministic across frames."
|
|
1681
1681
|
},
|
|
1682
|
+
{
|
|
1683
|
+
pattern: /crypto\.randomUUID\s*\(/,
|
|
1684
|
+
label: "crypto.randomUUID()",
|
|
1685
|
+
hint: "Use a seeded PRNG (e.g. a simple mulberry32) so renders are deterministic across frames."
|
|
1686
|
+
},
|
|
1682
1687
|
{
|
|
1683
1688
|
pattern: /gsap\.utils\.random\s*\(/,
|
|
1684
1689
|
label: "gsap.utils.random()",
|
package/dist/index.d.ts
CHANGED
|
@@ -107,9 +107,15 @@ interface ProjectLintResult {
|
|
|
107
107
|
totalErrors: number;
|
|
108
108
|
totalWarnings: number;
|
|
109
109
|
totalInfos: number;
|
|
110
|
+
unmountedCompositions?: string[];
|
|
111
|
+
}
|
|
112
|
+
/** The one line a run prints when it left unmounted compositions out. */
|
|
113
|
+
declare function unmountedNotice(count: number): string;
|
|
114
|
+
interface ProjectLintOptions {
|
|
115
|
+
includeUnmounted?: boolean;
|
|
110
116
|
}
|
|
111
117
|
declare function linkedSources(projectDir: string, html: string, compSrcPath?: string): Pick<HyperframeLinterOptions, "externalStyles" | "externalScripts">;
|
|
112
|
-
declare function lintProject(projectDir: string, entryFile?: string, hostOptions?: Pick<HyperframeLinterOptions, "host" | "isSubComposition"
|
|
118
|
+
declare function lintProject(projectDir: string, entryFile?: string, hostOptions?: Pick<HyperframeLinterOptions, "host" | "isSubComposition">, { includeUnmounted }?: ProjectLintOptions): Promise<ProjectLintResult>;
|
|
113
119
|
|
|
114
120
|
/** What the project leaves out; ask with a relative `/` path, a folder with a trailing `/`. */
|
|
115
121
|
declare function projectIgnore(projectDir: string): Ignore;
|
|
@@ -121,4 +127,4 @@ type AudioAttribute = "data-automation" | "data-fx-chain";
|
|
|
121
127
|
*/
|
|
122
128
|
declare function audioAttributeShapeError(attr: AudioAttribute, json: string): string | null;
|
|
123
129
|
|
|
124
|
-
export { type AudioAttribute, type HyperframeLintFinding, type HyperframeLintResult, type HyperframeLintSeverity, type HyperframeLinterOptions, LINT_RULE_COUNT, LINT_RULE_GROUP_COUNTS, type LintTimings, type ProjectLintResult, audioAttributeShapeError, linkedSources, lintHyperframeHtml, lintMediaUrls, lintProject, projectIgnore, shouldBlockRender };
|
|
130
|
+
export { type AudioAttribute, type HyperframeLintFinding, type HyperframeLintResult, type HyperframeLintSeverity, type HyperframeLinterOptions, LINT_RULE_COUNT, LINT_RULE_GROUP_COUNTS, type LintTimings, type ProjectLintOptions, type ProjectLintResult, audioAttributeShapeError, linkedSources, lintHyperframeHtml, lintMediaUrls, lintProject, projectIgnore, shouldBlockRender, unmountedNotice };
|
package/dist/index.js
CHANGED
|
@@ -1685,6 +1685,11 @@ var coreRules = [
|
|
|
1685
1685
|
label: "crypto.getRandomValues()",
|
|
1686
1686
|
hint: "Use a seeded PRNG (e.g. a simple mulberry32) so renders are deterministic across frames."
|
|
1687
1687
|
},
|
|
1688
|
+
{
|
|
1689
|
+
pattern: /crypto\.randomUUID\s*\(/,
|
|
1690
|
+
label: "crypto.randomUUID()",
|
|
1691
|
+
hint: "Use a seeded PRNG (e.g. a simple mulberry32) so renders are deterministic across frames."
|
|
1692
|
+
},
|
|
1688
1693
|
{
|
|
1689
1694
|
pattern: /gsap\.utils\.random\s*\(/,
|
|
1690
1695
|
label: "gsap.utils.random()",
|
|
@@ -7611,6 +7616,10 @@ function querySelectorAllIncludingTemplates(root, selector) {
|
|
|
7611
7616
|
}
|
|
7612
7617
|
return matches;
|
|
7613
7618
|
}
|
|
7619
|
+
function unmountedNotice(count) {
|
|
7620
|
+
const skipped = count === 1 ? "1 file in compositions/ is" : `${count} files in compositions/ are`;
|
|
7621
|
+
return `${skipped} not mounted from index.html, so not checked; --include-unmounted adds them.`;
|
|
7622
|
+
}
|
|
7614
7623
|
function contentDigest(html) {
|
|
7615
7624
|
return createHash("sha256").update(html).digest("hex").slice(0, 16);
|
|
7616
7625
|
}
|
|
@@ -7750,7 +7759,7 @@ function declaredProjectFontFamilies(projectDir, sources) {
|
|
|
7750
7759
|
}
|
|
7751
7760
|
return [...families];
|
|
7752
7761
|
}
|
|
7753
|
-
async function lintProject(projectDir, entryFile, hostOptions = {}) {
|
|
7762
|
+
async function lintProject(projectDir, entryFile, hostOptions = {}, { includeUnmounted = false } = {}) {
|
|
7754
7763
|
const indexPath = entryFile ? resolve(entryFile) : resolve(projectDir, "index.html");
|
|
7755
7764
|
if (entryFile && !isWithinProjectRoot2(projectDir, indexPath)) {
|
|
7756
7765
|
throw new Error(`Explicit lint entry is outside the project directory: ${entryFile}`);
|
|
@@ -7762,10 +7771,11 @@ async function lintProject(projectDir, entryFile, hostOptions = {}) {
|
|
|
7762
7771
|
let totalWarnings = 0;
|
|
7763
7772
|
let totalInfos = 0;
|
|
7764
7773
|
const rootHtml = readTextFile(indexPath);
|
|
7765
|
-
const
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7774
|
+
const mounted = mountedSources(projectDir, rootHtml, rootCompSrcPath);
|
|
7775
|
+
const mountedPaths = new Set(mounted.map((source) => source.compSrcPath));
|
|
7776
|
+
const unmountedCompositions = [];
|
|
7777
|
+
const unmountedSources = [];
|
|
7778
|
+
const projectFontFamilies = declaredProjectFontFamilies(projectDir, mounted);
|
|
7769
7779
|
const rootResult = await lintHyperframeHtml(rootHtml, {
|
|
7770
7780
|
...hostOptions,
|
|
7771
7781
|
filePath: indexPath,
|
|
@@ -7800,6 +7810,11 @@ async function lintProject(projectDir, entryFile, hostOptions = {}) {
|
|
|
7800
7810
|
const filePath = join4(compositionsDir, file);
|
|
7801
7811
|
const html = readTextFile(filePath);
|
|
7802
7812
|
const compSrcPath = `compositions/${file}`;
|
|
7813
|
+
if (!includeUnmounted && !mountedPaths.has(compSrcPath)) {
|
|
7814
|
+
unmountedSources.push({ html, compSrcPath });
|
|
7815
|
+
if (!isSnippetFragment(html)) unmountedCompositions.push(compSrcPath);
|
|
7816
|
+
continue;
|
|
7817
|
+
}
|
|
7803
7818
|
allHtmlSources.push({ html, compSrcPath });
|
|
7804
7819
|
if (isSnippetFragment(html)) continue;
|
|
7805
7820
|
const result = await lintHyperframeHtml(html, {
|
|
@@ -7828,7 +7843,7 @@ async function lintProject(projectDir, entryFile, hostOptions = {}) {
|
|
|
7828
7843
|
...lintTextureMaskAssetNotFound(projectDir, allHtmlSources),
|
|
7829
7844
|
...lintLinkedStylesheetAssets(projectDir, allHtmlSources),
|
|
7830
7845
|
...!entryFile ? lintMultipleRootCompositions(projectDir) : [],
|
|
7831
|
-
...!entryFile ? lintBlankRootWithStandaloneComposition(rootHtml, allHtmlSources) : [],
|
|
7846
|
+
...!entryFile ? lintBlankRootWithStandaloneComposition(rootHtml, [...allHtmlSources, ...unmountedSources]) : [],
|
|
7832
7847
|
...lintDuplicateAudioTracks(projectDir, rootHtml),
|
|
7833
7848
|
...lintMissingOrEmptySubComposition(projectDir, rootHtml),
|
|
7834
7849
|
...await lintVideoMediaStartPastEof(projectDir, allHtmlSources),
|
|
@@ -7850,7 +7865,7 @@ async function lintProject(projectDir, entryFile, hostOptions = {}) {
|
|
|
7850
7865
|
totalInfos++;
|
|
7851
7866
|
}
|
|
7852
7867
|
}
|
|
7853
|
-
return { results, totalErrors, totalWarnings, totalInfos };
|
|
7868
|
+
return { results, totalErrors, totalWarnings, totalInfos, unmountedCompositions };
|
|
7854
7869
|
}
|
|
7855
7870
|
function lintBlankRootWithStandaloneComposition(rootHtml, htmlSources) {
|
|
7856
7871
|
const { document: rootDocument } = parseHTML3(rootHtml);
|
|
@@ -7995,6 +8010,12 @@ function lintMissingLocalAsset(projectDir, htmlSources) {
|
|
|
7995
8010
|
}
|
|
7996
8011
|
return findings;
|
|
7997
8012
|
}
|
|
8013
|
+
function localCssUrl(match) {
|
|
8014
|
+
const rawUrl = match[1] ?? match[2] ?? match[3] ?? "";
|
|
8015
|
+
if (isUnresolvedAssetPlaceholder2(rawUrl)) return void 0;
|
|
8016
|
+
const url = cleanAssetUrl2(rawUrl);
|
|
8017
|
+
return url && !isRemoteOrInlineUrl2(url) ? url : void 0;
|
|
8018
|
+
}
|
|
7998
8019
|
function lintTextureMaskAssetNotFound(projectDir, htmlSources) {
|
|
7999
8020
|
const missingByFile = /* @__PURE__ */ new Map();
|
|
8000
8021
|
for (const { html, compSrcPath } of htmlSources) {
|
|
@@ -8010,10 +8031,8 @@ function lintTextureMaskAssetNotFound(projectDir, htmlSources) {
|
|
|
8010
8031
|
matches = [...cssSource.content.matchAll(MASK_IMAGE_URL_RE)];
|
|
8011
8032
|
}
|
|
8012
8033
|
for (const match of matches) {
|
|
8013
|
-
const
|
|
8014
|
-
if (
|
|
8015
|
-
const url = cleanAssetUrl2(rawUrl);
|
|
8016
|
-
if (!url || isRemoteOrInlineUrl2(url)) continue;
|
|
8034
|
+
const url = localCssUrl(match);
|
|
8035
|
+
if (!url) continue;
|
|
8017
8036
|
const candidates = resolveCssAssetCandidates(
|
|
8018
8037
|
projectDir,
|
|
8019
8038
|
url,
|
|
@@ -8068,10 +8087,8 @@ function lintLinkedStylesheetAssets(projectDir, htmlSources) {
|
|
|
8068
8087
|
root.walkDecls((declaration) => {
|
|
8069
8088
|
if (/^(?:-webkit-)?mask-image$/i.test(declaration.prop)) return;
|
|
8070
8089
|
for (const match of declaration.value.matchAll(CSS_URL_RE)) {
|
|
8071
|
-
const
|
|
8072
|
-
if (
|
|
8073
|
-
const url = cleanAssetUrl2(rawUrl);
|
|
8074
|
-
if (!url || isRemoteOrInlineUrl2(url) || url.startsWith("/")) continue;
|
|
8090
|
+
const url = localCssUrl(match);
|
|
8091
|
+
if (!url || url.startsWith("/")) continue;
|
|
8075
8092
|
if (resolveCssAssetCandidates(projectDir, url, void 0, rootRelativePath).some(existsSync3))
|
|
8076
8093
|
continue;
|
|
8077
8094
|
const key = `${rootRelativePath}\0${url}`;
|
|
@@ -8271,5 +8288,6 @@ export {
|
|
|
8271
8288
|
lintMediaUrls,
|
|
8272
8289
|
lintProject,
|
|
8273
8290
|
projectIgnore,
|
|
8274
|
-
shouldBlockRender
|
|
8291
|
+
shouldBlockRender,
|
|
8292
|
+
unmountedNotice
|
|
8275
8293
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/lint",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.21",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/heygen-com/hyperframes",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"linkedom": "^0.18.12",
|
|
37
37
|
"postcss": "^8.5.8",
|
|
38
38
|
"postcss-selector-parser": "^7.1.4",
|
|
39
|
-
"@hyperframes/parsers": "0.9.
|
|
39
|
+
"@hyperframes/parsers": "0.9.21"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@types/node": "^25.0.10",
|