@hyperframes/lint 0.8.221 → 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 +8 -0
- package/dist/browser.js +23 -7
- package/dist/index.d.ts +8 -0
- package/dist/index.js +151 -10
- package/package.json +2 -2
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
|
|
@@ -51,6 +58,7 @@ type HyperframeLinterOptions = {
|
|
|
51
58
|
* render time — the font will silently fall back to whatever the OS provides.
|
|
52
59
|
*/
|
|
53
60
|
distributed?: boolean;
|
|
61
|
+
projectFontFamilies?: string[];
|
|
54
62
|
/** Who is running the lint: Studio raises the structure rules to errors, the CLI keeps them warnings. */
|
|
55
63
|
host?: "studio" | "cli";
|
|
56
64
|
};
|
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 =
|
|
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
|
-
|
|
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
|
|
1564
|
-
|
|
1565
|
-
|
|
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({
|
|
@@ -6439,6 +6452,9 @@ function extractFontFaceFamilies(styles) {
|
|
|
6439
6452
|
}
|
|
6440
6453
|
return families;
|
|
6441
6454
|
}
|
|
6455
|
+
function declaredFontFamilies(styles, options) {
|
|
6456
|
+
return /* @__PURE__ */ new Set([...extractFontFaceFamilies(styles), ...options.projectFontFamilies ?? []]);
|
|
6457
|
+
}
|
|
6442
6458
|
function normalizeUsedFontName(part) {
|
|
6443
6459
|
const name = part.trim().replace(/\s*!important\s*$/i, "").replace(/^['"]|['"]$/g, "").trim().toLowerCase();
|
|
6444
6460
|
if (!name || name.includes("(") || name.includes(")")) return null;
|
|
@@ -6548,7 +6564,7 @@ var fontRules = [
|
|
|
6548
6564
|
// so there is nothing for the author to act on.
|
|
6549
6565
|
({ styles, options }) => {
|
|
6550
6566
|
if (!options.distributed) return [];
|
|
6551
|
-
const declared =
|
|
6567
|
+
const declared = declaredFontFamilies(styles, options);
|
|
6552
6568
|
const used = extractUsedFontFamilies(styles);
|
|
6553
6569
|
const aliased = collectAliasedFonts(used, declared);
|
|
6554
6570
|
if (aliased.length === 0) return [];
|
|
@@ -6564,7 +6580,7 @@ var fontRules = [
|
|
|
6564
6580
|
({ styles, source, rawSource, options, locate }) => {
|
|
6565
6581
|
if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];
|
|
6566
6582
|
const findings = [];
|
|
6567
|
-
const declared =
|
|
6583
|
+
const declared = declaredFontFamilies(styles, options);
|
|
6568
6584
|
const used = extractUsedFontFamilies(styles);
|
|
6569
6585
|
const googleFonts = collectGoogleFontFamilies(source, styles);
|
|
6570
6586
|
const undeclared = used.filter(
|
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
|
|
@@ -51,6 +58,7 @@ type HyperframeLinterOptions = {
|
|
|
51
58
|
* render time — the font will silently fall back to whatever the OS provides.
|
|
52
59
|
*/
|
|
53
60
|
distributed?: boolean;
|
|
61
|
+
projectFontFamilies?: string[];
|
|
54
62
|
/** Who is running the lint: Studio raises the structure rules to errors, the CLI keeps them warnings. */
|
|
55
63
|
host?: "studio" | "cli";
|
|
56
64
|
};
|
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 =
|
|
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
|
-
|
|
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
|
|
1570
|
-
|
|
1571
|
-
|
|
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({
|
|
@@ -6445,6 +6458,9 @@ function extractFontFaceFamilies(styles) {
|
|
|
6445
6458
|
}
|
|
6446
6459
|
return families;
|
|
6447
6460
|
}
|
|
6461
|
+
function declaredFontFamilies(styles, options) {
|
|
6462
|
+
return /* @__PURE__ */ new Set([...extractFontFaceFamilies(styles), ...options.projectFontFamilies ?? []]);
|
|
6463
|
+
}
|
|
6448
6464
|
function normalizeUsedFontName(part) {
|
|
6449
6465
|
const name = part.trim().replace(/\s*!important\s*$/i, "").replace(/^['"]|['"]$/g, "").trim().toLowerCase();
|
|
6450
6466
|
if (!name || name.includes("(") || name.includes(")")) return null;
|
|
@@ -6554,7 +6570,7 @@ var fontRules = [
|
|
|
6554
6570
|
// so there is nothing for the author to act on.
|
|
6555
6571
|
({ styles, options }) => {
|
|
6556
6572
|
if (!options.distributed) return [];
|
|
6557
|
-
const declared =
|
|
6573
|
+
const declared = declaredFontFamilies(styles, options);
|
|
6558
6574
|
const used = extractUsedFontFamilies(styles);
|
|
6559
6575
|
const aliased = collectAliasedFonts(used, declared);
|
|
6560
6576
|
if (aliased.length === 0) return [];
|
|
@@ -6570,7 +6586,7 @@ var fontRules = [
|
|
|
6570
6586
|
({ styles, source, rawSource, options, locate }) => {
|
|
6571
6587
|
if (isRegistrySourceFile(options.filePath) || isRegistryInstalledFile(rawSource)) return [];
|
|
6572
6588
|
const findings = [];
|
|
6573
|
-
const declared =
|
|
6589
|
+
const declared = declaredFontFamilies(styles, options);
|
|
6574
6590
|
const used = extractUsedFontFamilies(styles);
|
|
6575
6591
|
const googleFonts = collectGoogleFontFamilies(source, styles);
|
|
6576
6592
|
const undeclared = used.filter(
|
|
@@ -7489,6 +7505,30 @@ function collectExternalStyles(projectDir, html, compSrcPath) {
|
|
|
7489
7505
|
}
|
|
7490
7506
|
return styles;
|
|
7491
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, "&").replace(/"/g, """)}"`).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
|
+
}
|
|
7492
7532
|
function collectCssSources(projectDir, html, compSrcPath) {
|
|
7493
7533
|
const sources = [];
|
|
7494
7534
|
const { document } = parseHTML3(html);
|
|
@@ -7522,6 +7562,42 @@ function resolveCssAssetCandidates(projectDir, url, htmlCompSrcPath, cssRootRela
|
|
|
7522
7562
|
}
|
|
7523
7563
|
return resolveLocalAssetCandidates(projectDir, url);
|
|
7524
7564
|
}
|
|
7565
|
+
function mountedSources(projectDir, rootHtml, rootCompSrcPath) {
|
|
7566
|
+
const sources = [{ html: rootHtml, compSrcPath: rootCompSrcPath }];
|
|
7567
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7568
|
+
for (const source of sources) {
|
|
7569
|
+
const { document } = parseHTML3(source.html);
|
|
7570
|
+
for (const host of querySelectorAllIncludingTemplates(document, "[data-composition-src]")) {
|
|
7571
|
+
const src = host.getAttribute("data-composition-src")?.trim();
|
|
7572
|
+
if (!src || isUnresolvedAssetPlaceholder2(src) || isRemoteOrInlineUrl2(src)) continue;
|
|
7573
|
+
const path = resolve(projectDir, src);
|
|
7574
|
+
if (seen.has(path) || !isWithinProjectRoot2(projectDir, path)) continue;
|
|
7575
|
+
seen.add(path);
|
|
7576
|
+
const read = readProjectFile2(path);
|
|
7577
|
+
if (read.kind !== "file") continue;
|
|
7578
|
+
sources.push({
|
|
7579
|
+
html: read.text,
|
|
7580
|
+
compSrcPath: relative2(resolve(projectDir), path).replace(/\\/g, "/")
|
|
7581
|
+
});
|
|
7582
|
+
}
|
|
7583
|
+
}
|
|
7584
|
+
return sources;
|
|
7585
|
+
}
|
|
7586
|
+
function declaredProjectFontFamilies(projectDir, sources) {
|
|
7587
|
+
const families = /* @__PURE__ */ new Set();
|
|
7588
|
+
for (const { html, compSrcPath } of sources) {
|
|
7589
|
+
const { document } = parseHTML3(html);
|
|
7590
|
+
const styles = [
|
|
7591
|
+
...querySelectorAllIncludingTemplates(document, "style").map((style) => ({
|
|
7592
|
+
content: style.textContent ?? ""
|
|
7593
|
+
})),
|
|
7594
|
+
...collectLocalStylesheets(projectDir, document, compSrcPath)
|
|
7595
|
+
];
|
|
7596
|
+
for (const family of extractFontFaceFamilies(styles)) families.add(family);
|
|
7597
|
+
for (const family of collectGoogleFontFamilies(html, styles)) families.add(family);
|
|
7598
|
+
}
|
|
7599
|
+
return [...families];
|
|
7600
|
+
}
|
|
7525
7601
|
async function lintProject(projectDir, entryFile, hostOptions = {}) {
|
|
7526
7602
|
const indexPath = entryFile ? resolve(entryFile) : resolve(projectDir, "index.html");
|
|
7527
7603
|
if (entryFile && !isWithinProjectRoot2(projectDir, indexPath)) {
|
|
@@ -7534,11 +7610,17 @@ async function lintProject(projectDir, entryFile, hostOptions = {}) {
|
|
|
7534
7610
|
let totalWarnings = 0;
|
|
7535
7611
|
let totalInfos = 0;
|
|
7536
7612
|
const rootHtml = readFileSync(indexPath, "utf-8");
|
|
7613
|
+
const projectFontFamilies = declaredProjectFontFamilies(
|
|
7614
|
+
projectDir,
|
|
7615
|
+
mountedSources(projectDir, rootHtml, rootCompSrcPath)
|
|
7616
|
+
);
|
|
7537
7617
|
const rootResult = await lintHyperframeHtml(rootHtml, {
|
|
7538
7618
|
...hostOptions,
|
|
7539
7619
|
filePath: indexPath,
|
|
7540
7620
|
compSrcPath: rootFile,
|
|
7541
|
-
externalStyles: collectExternalStyles(projectDir, rootHtml, rootCompSrcPath)
|
|
7621
|
+
externalStyles: collectExternalStyles(projectDir, rootHtml, rootCompSrcPath),
|
|
7622
|
+
projectFontFamilies,
|
|
7623
|
+
externalScripts: collectExternalScripts(projectDir, rootHtml, rootCompSrcPath)
|
|
7542
7624
|
});
|
|
7543
7625
|
results.push({ file: rootFile, result: rootResult, contentHash: contentDigest(rootHtml) });
|
|
7544
7626
|
totalErrors += rootResult.errorCount;
|
|
@@ -7572,7 +7654,9 @@ async function lintProject(projectDir, entryFile, hostOptions = {}) {
|
|
|
7572
7654
|
filePath,
|
|
7573
7655
|
isSubComposition: true,
|
|
7574
7656
|
compSrcPath,
|
|
7575
|
-
externalStyles: collectExternalStyles(projectDir, html, compSrcPath)
|
|
7657
|
+
externalStyles: collectExternalStyles(projectDir, html, compSrcPath),
|
|
7658
|
+
projectFontFamilies,
|
|
7659
|
+
externalScripts: collectExternalScripts(projectDir, html, compSrcPath)
|
|
7576
7660
|
});
|
|
7577
7661
|
results.push({
|
|
7578
7662
|
file: `compositions/${file}`,
|
|
@@ -7590,6 +7674,7 @@ async function lintProject(projectDir, entryFile, hostOptions = {}) {
|
|
|
7590
7674
|
...lintAudioSrcNotFound(projectDir, allHtmlSources),
|
|
7591
7675
|
...lintMissingLocalAsset(projectDir, allHtmlSources),
|
|
7592
7676
|
...lintTextureMaskAssetNotFound(projectDir, allHtmlSources),
|
|
7677
|
+
...lintLinkedStylesheetAssets(projectDir, allHtmlSources),
|
|
7593
7678
|
...!entryFile ? lintMultipleRootCompositions(projectDir) : [],
|
|
7594
7679
|
...!entryFile ? lintBlankRootWithStandaloneComposition(rootHtml, allHtmlSources) : [],
|
|
7595
7680
|
...lintDuplicateAudioTracks(projectDir, rootHtml),
|
|
@@ -7799,6 +7884,62 @@ function lintTextureMaskAssetNotFound(projectDir, htmlSources) {
|
|
|
7799
7884
|
};
|
|
7800
7885
|
});
|
|
7801
7886
|
}
|
|
7887
|
+
function nearestAncestorMatch(projectDir, cssRootRelativePath, url) {
|
|
7888
|
+
const root = resolve(projectDir);
|
|
7889
|
+
for (let dir = resolve(root, dirname2(cssRootRelativePath), ".."); ; dir = dirname2(dir)) {
|
|
7890
|
+
if (!isWithinProjectRoot2(projectDir, dir)) return null;
|
|
7891
|
+
if (resolveLocalAssetCandidates(projectDir, relative2(root, join3(dir, url))).some(existsSync2)) {
|
|
7892
|
+
return relative2(dirname2(resolve(root, cssRootRelativePath)), join3(dir, url)).replace(
|
|
7893
|
+
/\\/g,
|
|
7894
|
+
"/"
|
|
7895
|
+
);
|
|
7896
|
+
}
|
|
7897
|
+
if (dir === root) return null;
|
|
7898
|
+
}
|
|
7899
|
+
}
|
|
7900
|
+
function lintLinkedStylesheetAssets(projectDir, htmlSources) {
|
|
7901
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7902
|
+
const findings = [];
|
|
7903
|
+
for (const { html, compSrcPath } of htmlSources) {
|
|
7904
|
+
for (const { content, rootRelativePath } of collectLocalStylesheets(
|
|
7905
|
+
projectDir,
|
|
7906
|
+
parseHTML3(html).document,
|
|
7907
|
+
compSrcPath
|
|
7908
|
+
)) {
|
|
7909
|
+
let root;
|
|
7910
|
+
try {
|
|
7911
|
+
root = postcss4.parse(content);
|
|
7912
|
+
} catch (error) {
|
|
7913
|
+
if (!(error instanceof postcss4.CssSyntaxError)) throw error;
|
|
7914
|
+
continue;
|
|
7915
|
+
}
|
|
7916
|
+
root.walkDecls((declaration) => {
|
|
7917
|
+
if (/^(?:-webkit-)?mask-image$/i.test(declaration.prop)) return;
|
|
7918
|
+
for (const match of declaration.value.matchAll(CSS_URL_RE)) {
|
|
7919
|
+
const rawUrl = match[1] ?? match[2] ?? match[3] ?? "";
|
|
7920
|
+
if (isUnresolvedAssetPlaceholder2(rawUrl)) continue;
|
|
7921
|
+
const url = cleanAssetUrl2(rawUrl);
|
|
7922
|
+
if (!url || isRemoteOrInlineUrl2(url) || url.startsWith("/")) continue;
|
|
7923
|
+
if (resolveCssAssetCandidates(projectDir, url, void 0, rootRelativePath).some(existsSync2))
|
|
7924
|
+
continue;
|
|
7925
|
+
const key = `${rootRelativePath}\0${url}`;
|
|
7926
|
+
if (seen.has(key)) continue;
|
|
7927
|
+
seen.add(key);
|
|
7928
|
+
const found = nearestAncestorMatch(projectDir, rootRelativePath, url);
|
|
7929
|
+
findings.push({
|
|
7930
|
+
code: "missing_stylesheet_asset",
|
|
7931
|
+
severity: "warning",
|
|
7932
|
+
file: join3(projectDir, rootRelativePath),
|
|
7933
|
+
message: `${rootRelativePath} references url(${url}), which is not found beside the stylesheet (looked in ${dirname2(rootRelativePath)}/). The browser resolves url() from the stylesheet, so the file will 404.`,
|
|
7934
|
+
fixHint: found ? `A file exists at "${found}" relative to the stylesheet. Change the url() to that path.` : `Add "${url}" beside the stylesheet, or point the url() at an existing file.`
|
|
7935
|
+
});
|
|
7936
|
+
}
|
|
7937
|
+
});
|
|
7938
|
+
}
|
|
7939
|
+
}
|
|
7940
|
+
return findings;
|
|
7941
|
+
}
|
|
7942
|
+
var PAGES_OPENED_BESIDE_INDEX = /* @__PURE__ */ new Set(["caption-skin.html", "podcast-lanes.html"]);
|
|
7802
7943
|
function lintMultipleRootCompositions(projectDir) {
|
|
7803
7944
|
const findings = [];
|
|
7804
7945
|
try {
|
|
@@ -7807,7 +7948,7 @@ function lintMultipleRootCompositions(projectDir) {
|
|
|
7807
7948
|
);
|
|
7808
7949
|
const rootCompositions = [];
|
|
7809
7950
|
for (const file of rootHtmlFiles) {
|
|
7810
|
-
if (file
|
|
7951
|
+
if (PAGES_OPENED_BESIDE_INDEX.has(file)) continue;
|
|
7811
7952
|
const content = readFileSync(join3(projectDir, file), "utf-8");
|
|
7812
7953
|
if (/data-composition-id/i.test(content)) {
|
|
7813
7954
|
rootCompositions.push(file);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/lint",
|
|
3
|
-
"version": "0.8.
|
|
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.
|
|
38
|
+
"@hyperframes/parsers": "0.8.223"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^25.0.10",
|