@hyperframes/lint 0.7.106 → 0.7.108
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 +39 -1
- package/dist/browser.js.map +1 -1
- package/dist/index.js +39 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/browser.js
CHANGED
|
@@ -862,6 +862,23 @@ var coreRules = [
|
|
|
862
862
|
|
|
863
863
|
// src/rules/media.ts
|
|
864
864
|
import { validateColorGradingContract } from "@hyperframes/parsers/color-grading-contract";
|
|
865
|
+
function tweensVolumeInSameCall(script, id) {
|
|
866
|
+
const selector = new RegExp(`#${escapeRegExp2(id)}(?![\\w-])`, "g");
|
|
867
|
+
for (let hit = selector.exec(script); hit; hit = selector.exec(script)) {
|
|
868
|
+
let depth = 0;
|
|
869
|
+
const limit = Math.min(script.length, hit.index + 2e3);
|
|
870
|
+
for (let i = hit.index; i < limit; i += 1) {
|
|
871
|
+
const ch = script[i];
|
|
872
|
+
if (ch === "(") depth += 1;
|
|
873
|
+
else if (ch === ")") {
|
|
874
|
+
if (depth === 0) break;
|
|
875
|
+
depth -= 1;
|
|
876
|
+
} else if (ch === ";" && depth === 0) break;
|
|
877
|
+
else if (ch === "v" && /^volume\s*:/.test(script.slice(i))) return true;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
return false;
|
|
881
|
+
}
|
|
865
882
|
function escapeRegExp2(value) {
|
|
866
883
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
867
884
|
}
|
|
@@ -1383,8 +1400,29 @@ var mediaRules = [
|
|
|
1383
1400
|
return findings;
|
|
1384
1401
|
},
|
|
1385
1402
|
// imperative_media_control
|
|
1386
|
-
findImperativeMediaControlFindings
|
|
1403
|
+
findImperativeMediaControlFindings,
|
|
1404
|
+
// audio_volume_double_automation
|
|
1405
|
+
findVolumeDoubleAutomationFindings
|
|
1387
1406
|
];
|
|
1407
|
+
function findVolumeDoubleAutomationFindings(ctx) {
|
|
1408
|
+
const automated = ctx.tags.filter((tag) => isMediaTag(tag.name)).map((tag) => ({ tag, automation: readDecodedAttr(tag.raw, "data-automation") })).filter((entry) => entry.automation && /"target"\s*:\s*"volume"/.test(entry.automation)).map((entry) => ({ ...entry, id: readAttr(entry.tag.raw, "id") })).filter((entry) => Boolean(entry.id));
|
|
1409
|
+
if (automated.length === 0) return [];
|
|
1410
|
+
const script = ctx.scripts.map((block) => stripJsComments(block.content)).join("\n");
|
|
1411
|
+
const findings = [];
|
|
1412
|
+
for (const { tag, id } of automated) {
|
|
1413
|
+
const tweened = tweensVolumeInSameCall(script, id);
|
|
1414
|
+
if (!tweened) continue;
|
|
1415
|
+
findings.push({
|
|
1416
|
+
code: "audio_volume_double_automation",
|
|
1417
|
+
severity: "warning",
|
|
1418
|
+
message: `#${id} has both a volume automation lane and a GSAP tween on \`volume\`. The lane wins \u2014 the tween is ignored in preview and in the render.`,
|
|
1419
|
+
elementId: id,
|
|
1420
|
+
fixHint: "Keep one of them: delete the volume lane to go back to tweening, or drop the tween and shape the level in the automation lane.",
|
|
1421
|
+
snippet: truncateSnippet(tag.raw)
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
return findings;
|
|
1425
|
+
}
|
|
1388
1426
|
|
|
1389
1427
|
// src/rules/gsap.ts
|
|
1390
1428
|
async function loadParseGsapScript() {
|