@hyperframes/lint 0.8.184 → 0.8.186
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 +82 -13
- package/dist/index.js +82 -13
- package/package.json +2 -2
package/dist/browser.js
CHANGED
|
@@ -4,6 +4,7 @@ import { Parser as Parser2 } from "htmlparser2";
|
|
|
4
4
|
// src/utils.ts
|
|
5
5
|
import { Parser } from "htmlparser2";
|
|
6
6
|
import { parse } from "acorn";
|
|
7
|
+
import { base, recursive, simple } from "acorn-walk";
|
|
7
8
|
var COMPOSITION_ID_IN_CSS_PATTERN = /\[data-composition-id=["']([^"']+)["']\]/g;
|
|
8
9
|
var TIMELINE_REGISTRY_INIT_PATTERN = /window\.__timelines\s*=\s*window\.__timelines\s*\|\|\s*\{\}|window\.__timelines\s*=\s*\{\}|window\.__timelines\s*\?\?=\s*\{\}/i;
|
|
9
10
|
var TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN = /window\.__timelines\s*=\s*\{\s*(?:["'][^"']+["']|[A-Za-z_$][\w$]*)\s*:/i;
|
|
@@ -366,6 +367,74 @@ function scanJsComments(source) {
|
|
|
366
367
|
function stripJsComments(source) {
|
|
367
368
|
return scanJsComments(source).out;
|
|
368
369
|
}
|
|
370
|
+
function isGsapLibraryComment(comment) {
|
|
371
|
+
if (comment.type !== "Block") return false;
|
|
372
|
+
const { value } = comment;
|
|
373
|
+
const src = /^\s*inlined:\s*(\S+)\s*$/.exec(value)?.[1]?.split(/[?#]/)[0];
|
|
374
|
+
return value.startsWith("!") && /\bGreenSock\b/.test(value) || src !== void 0 && /(?:^|\/)gsap(?:@[^/]+)?\/dist\/[^/]+\.js$/.test(src);
|
|
375
|
+
}
|
|
376
|
+
function isUmdWrapperCall(call) {
|
|
377
|
+
const [scope, factory] = call.arguments;
|
|
378
|
+
if (call.callee.type !== "FunctionExpression" || call.arguments.length !== 2 || scope?.type !== "ThisExpression" || factory?.type !== "FunctionExpression")
|
|
379
|
+
return false;
|
|
380
|
+
let checksAmd = false;
|
|
381
|
+
recursive(call.callee.body, null, {
|
|
382
|
+
Function() {
|
|
383
|
+
},
|
|
384
|
+
MemberExpression(member, state, visit) {
|
|
385
|
+
if (!member.computed && member.object.type === "Identifier" && member.object.name === "define" && member.property.type === "Identifier" && member.property.name === "amd")
|
|
386
|
+
checksAmd = true;
|
|
387
|
+
base.MemberExpression?.(member, state, visit);
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
return checksAmd;
|
|
391
|
+
}
|
|
392
|
+
function bannerOwner(banner, source, commentAt, wrappers) {
|
|
393
|
+
let next = banner.end;
|
|
394
|
+
for (; ; ) {
|
|
395
|
+
while (/[\s!;(]/.test(source[next] ?? "")) next++;
|
|
396
|
+
const comment = commentAt.get(next);
|
|
397
|
+
if (!comment) break;
|
|
398
|
+
next = comment.end;
|
|
399
|
+
}
|
|
400
|
+
return wrappers.find((call) => call.start === next);
|
|
401
|
+
}
|
|
402
|
+
function findInlinedGsapLibrarySpans(source) {
|
|
403
|
+
if (!/GreenSock|inlined:/.test(source)) return [];
|
|
404
|
+
const comments = [];
|
|
405
|
+
let program;
|
|
406
|
+
try {
|
|
407
|
+
program = parse(source, {
|
|
408
|
+
ecmaVersion: "latest",
|
|
409
|
+
sourceType: "script",
|
|
410
|
+
allowReturnOutsideFunction: true,
|
|
411
|
+
onComment: comments
|
|
412
|
+
});
|
|
413
|
+
} catch {
|
|
414
|
+
return [];
|
|
415
|
+
}
|
|
416
|
+
const banners = comments.filter(isGsapLibraryComment);
|
|
417
|
+
const wrappers = [];
|
|
418
|
+
simple(program, {
|
|
419
|
+
CallExpression(call) {
|
|
420
|
+
if (isUmdWrapperCall(call)) wrappers.push(call);
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
const commentAt = new Map(comments.map((comment) => [comment.start, comment]));
|
|
424
|
+
const owners = /* @__PURE__ */ new Set();
|
|
425
|
+
for (const banner of banners) {
|
|
426
|
+
const owner = bannerOwner(banner, source, commentAt, wrappers);
|
|
427
|
+
if (owner) owners.add(owner);
|
|
428
|
+
}
|
|
429
|
+
return [...owners].map((call) => [call.start, call.end]);
|
|
430
|
+
}
|
|
431
|
+
function blankInlinedGsapLibrary(source) {
|
|
432
|
+
let out = source;
|
|
433
|
+
for (const [start, end] of findInlinedGsapLibrarySpans(source)) {
|
|
434
|
+
out = out.slice(0, start) + " ".repeat(end - start) + out.slice(end);
|
|
435
|
+
}
|
|
436
|
+
return out;
|
|
437
|
+
}
|
|
369
438
|
function stripJsCode(source) {
|
|
370
439
|
const { out, balanced } = scanJsComments(source);
|
|
371
440
|
return balanced ? stripJsStringLiterals(out) : source;
|
|
@@ -1497,7 +1566,7 @@ var coreRules = [
|
|
|
1497
1566
|
}
|
|
1498
1567
|
];
|
|
1499
1568
|
for (const script of scripts) {
|
|
1500
|
-
const withoutComments2 = stripJsComments(script.content);
|
|
1569
|
+
const withoutComments2 = stripJsComments(blankInlinedGsapLibrary(script.content));
|
|
1501
1570
|
const executable = stripStringLiterals(withoutComments2);
|
|
1502
1571
|
for (const { pattern, label, hint, scansStrings } of patterns) {
|
|
1503
1572
|
const match = pattern.exec(scansStrings ? withoutComments2 : executable);
|
|
@@ -1699,10 +1768,10 @@ function srcKind(src) {
|
|
|
1699
1768
|
} catch {
|
|
1700
1769
|
pathname = stripped.split("?")[0]?.split("#")[0] ?? stripped;
|
|
1701
1770
|
}
|
|
1702
|
-
const
|
|
1703
|
-
const dot =
|
|
1771
|
+
const base2 = pathname.split("/").pop() ?? "";
|
|
1772
|
+
const dot = base2.lastIndexOf(".");
|
|
1704
1773
|
if (dot < 0) return null;
|
|
1705
|
-
const ext =
|
|
1774
|
+
const ext = base2.slice(dot + 1).toLowerCase();
|
|
1706
1775
|
if (IMAGE_SRC_EXT.has(ext)) return "image";
|
|
1707
1776
|
if (VIDEO_SRC_EXT.has(ext)) return "video";
|
|
1708
1777
|
if (AUDIO_SRC_EXT.has(ext)) return "audio";
|
|
@@ -2497,7 +2566,7 @@ function findAudioGroupCarveAttrFindings(ctx) {
|
|
|
2497
2566
|
|
|
2498
2567
|
// src/scriptPositions.ts
|
|
2499
2568
|
import { parse as parse2 } from "acorn";
|
|
2500
|
-
import { simple } from "acorn-walk";
|
|
2569
|
+
import { simple as simple2 } from "acorn-walk";
|
|
2501
2570
|
var callIndexes = /* @__PURE__ */ new WeakMap();
|
|
2502
2571
|
function callsFor(script) {
|
|
2503
2572
|
const cached = callIndexes.get(script);
|
|
@@ -2509,7 +2578,7 @@ function callsFor(script) {
|
|
|
2509
2578
|
sourceType: "script",
|
|
2510
2579
|
allowReturnOutsideFunction: true
|
|
2511
2580
|
});
|
|
2512
|
-
|
|
2581
|
+
simple2(ast, {
|
|
2513
2582
|
CallExpression: (node) => {
|
|
2514
2583
|
calls.push(node);
|
|
2515
2584
|
}
|
|
@@ -4048,8 +4117,8 @@ function targetedSelectorTokens(selector) {
|
|
|
4048
4117
|
const compounds = group.trim().split(/[\s>+~]+/).filter(Boolean);
|
|
4049
4118
|
const last = compounds[compounds.length - 1];
|
|
4050
4119
|
if (!last) continue;
|
|
4051
|
-
const
|
|
4052
|
-
if (
|
|
4120
|
+
const simple4 = last.match(/[#.][A-Za-z0-9_-]+/g);
|
|
4121
|
+
if (simple4) for (const token of simple4) tokens.add(token);
|
|
4053
4122
|
}
|
|
4054
4123
|
return tokens;
|
|
4055
4124
|
}
|
|
@@ -6378,7 +6447,7 @@ var structureRules = [
|
|
|
6378
6447
|
|
|
6379
6448
|
// src/shaderDomains.ts
|
|
6380
6449
|
import { parse as parse3, parseExpressionAt } from "acorn";
|
|
6381
|
-
import { simple as
|
|
6450
|
+
import { simple as simple3 } from "acorn-walk";
|
|
6382
6451
|
function withoutComments(source) {
|
|
6383
6452
|
return source.replace(/\/\*[\s\S]*?\*\/|\/\/[^\r\n]*/g, (text) => text.replace(/[^\r\n]/g, " "));
|
|
6384
6453
|
}
|
|
@@ -6390,7 +6459,7 @@ function staticShaders(source) {
|
|
|
6390
6459
|
sourceType: "module",
|
|
6391
6460
|
allowReturnOutsideFunction: true
|
|
6392
6461
|
});
|
|
6393
|
-
|
|
6462
|
+
simple3(ast, {
|
|
6394
6463
|
Literal(node) {
|
|
6395
6464
|
if (typeof node.value !== "string") return;
|
|
6396
6465
|
shaders.push({
|
|
@@ -6437,8 +6506,8 @@ function zeroFlooredDot(a, b) {
|
|
|
6437
6506
|
}
|
|
6438
6507
|
function unsafeCosinePower(call) {
|
|
6439
6508
|
if (call.arguments.length !== 2) return false;
|
|
6440
|
-
const [
|
|
6441
|
-
return
|
|
6509
|
+
const [base2] = call.arguments;
|
|
6510
|
+
return base2?.type === "BinaryExpression" && base2.operator === "-" && base2.left.type !== "PrivateIdentifier" && isNumber(base2.left, 1) && unboundedCosine(base2.right);
|
|
6442
6511
|
}
|
|
6443
6512
|
function unsafePowOffsets(source) {
|
|
6444
6513
|
const offsets = [];
|
|
@@ -6446,7 +6515,7 @@ function unsafePowOffsets(source) {
|
|
|
6446
6515
|
for (const match of masked.matchAll(/\bpow\s*\(/g)) {
|
|
6447
6516
|
try {
|
|
6448
6517
|
const expression = parseExpressionAt(masked, match.index, { ecmaVersion: "latest" });
|
|
6449
|
-
|
|
6518
|
+
simple3(expression, {
|
|
6450
6519
|
CallExpression(node) {
|
|
6451
6520
|
if (node.start === match.index && unsafeCosinePower(node)) offsets.push(node.start);
|
|
6452
6521
|
}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { Parser as Parser2 } from "htmlparser2";
|
|
|
4
4
|
// src/utils.ts
|
|
5
5
|
import { Parser } from "htmlparser2";
|
|
6
6
|
import { parse } from "acorn";
|
|
7
|
+
import { base, recursive, simple } from "acorn-walk";
|
|
7
8
|
var COMPOSITION_ID_IN_CSS_PATTERN = /\[data-composition-id=["']([^"']+)["']\]/g;
|
|
8
9
|
var TIMELINE_REGISTRY_INIT_PATTERN = /window\.__timelines\s*=\s*window\.__timelines\s*\|\|\s*\{\}|window\.__timelines\s*=\s*\{\}|window\.__timelines\s*\?\?=\s*\{\}/i;
|
|
9
10
|
var TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN = /window\.__timelines\s*=\s*\{\s*(?:["'][^"']+["']|[A-Za-z_$][\w$]*)\s*:/i;
|
|
@@ -366,6 +367,74 @@ function scanJsComments(source) {
|
|
|
366
367
|
function stripJsComments(source) {
|
|
367
368
|
return scanJsComments(source).out;
|
|
368
369
|
}
|
|
370
|
+
function isGsapLibraryComment(comment) {
|
|
371
|
+
if (comment.type !== "Block") return false;
|
|
372
|
+
const { value } = comment;
|
|
373
|
+
const src = /^\s*inlined:\s*(\S+)\s*$/.exec(value)?.[1]?.split(/[?#]/)[0];
|
|
374
|
+
return value.startsWith("!") && /\bGreenSock\b/.test(value) || src !== void 0 && /(?:^|\/)gsap(?:@[^/]+)?\/dist\/[^/]+\.js$/.test(src);
|
|
375
|
+
}
|
|
376
|
+
function isUmdWrapperCall(call) {
|
|
377
|
+
const [scope, factory] = call.arguments;
|
|
378
|
+
if (call.callee.type !== "FunctionExpression" || call.arguments.length !== 2 || scope?.type !== "ThisExpression" || factory?.type !== "FunctionExpression")
|
|
379
|
+
return false;
|
|
380
|
+
let checksAmd = false;
|
|
381
|
+
recursive(call.callee.body, null, {
|
|
382
|
+
Function() {
|
|
383
|
+
},
|
|
384
|
+
MemberExpression(member, state, visit) {
|
|
385
|
+
if (!member.computed && member.object.type === "Identifier" && member.object.name === "define" && member.property.type === "Identifier" && member.property.name === "amd")
|
|
386
|
+
checksAmd = true;
|
|
387
|
+
base.MemberExpression?.(member, state, visit);
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
return checksAmd;
|
|
391
|
+
}
|
|
392
|
+
function bannerOwner(banner, source, commentAt, wrappers) {
|
|
393
|
+
let next = banner.end;
|
|
394
|
+
for (; ; ) {
|
|
395
|
+
while (/[\s!;(]/.test(source[next] ?? "")) next++;
|
|
396
|
+
const comment = commentAt.get(next);
|
|
397
|
+
if (!comment) break;
|
|
398
|
+
next = comment.end;
|
|
399
|
+
}
|
|
400
|
+
return wrappers.find((call) => call.start === next);
|
|
401
|
+
}
|
|
402
|
+
function findInlinedGsapLibrarySpans(source) {
|
|
403
|
+
if (!/GreenSock|inlined:/.test(source)) return [];
|
|
404
|
+
const comments = [];
|
|
405
|
+
let program;
|
|
406
|
+
try {
|
|
407
|
+
program = parse(source, {
|
|
408
|
+
ecmaVersion: "latest",
|
|
409
|
+
sourceType: "script",
|
|
410
|
+
allowReturnOutsideFunction: true,
|
|
411
|
+
onComment: comments
|
|
412
|
+
});
|
|
413
|
+
} catch {
|
|
414
|
+
return [];
|
|
415
|
+
}
|
|
416
|
+
const banners = comments.filter(isGsapLibraryComment);
|
|
417
|
+
const wrappers = [];
|
|
418
|
+
simple(program, {
|
|
419
|
+
CallExpression(call) {
|
|
420
|
+
if (isUmdWrapperCall(call)) wrappers.push(call);
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
const commentAt = new Map(comments.map((comment) => [comment.start, comment]));
|
|
424
|
+
const owners = /* @__PURE__ */ new Set();
|
|
425
|
+
for (const banner of banners) {
|
|
426
|
+
const owner = bannerOwner(banner, source, commentAt, wrappers);
|
|
427
|
+
if (owner) owners.add(owner);
|
|
428
|
+
}
|
|
429
|
+
return [...owners].map((call) => [call.start, call.end]);
|
|
430
|
+
}
|
|
431
|
+
function blankInlinedGsapLibrary(source) {
|
|
432
|
+
let out = source;
|
|
433
|
+
for (const [start, end] of findInlinedGsapLibrarySpans(source)) {
|
|
434
|
+
out = out.slice(0, start) + " ".repeat(end - start) + out.slice(end);
|
|
435
|
+
}
|
|
436
|
+
return out;
|
|
437
|
+
}
|
|
369
438
|
function stripJsCode(source) {
|
|
370
439
|
const { out, balanced } = scanJsComments(source);
|
|
371
440
|
return balanced ? stripJsStringLiterals(out) : source;
|
|
@@ -1503,7 +1572,7 @@ var coreRules = [
|
|
|
1503
1572
|
}
|
|
1504
1573
|
];
|
|
1505
1574
|
for (const script of scripts) {
|
|
1506
|
-
const withoutComments2 = stripJsComments(script.content);
|
|
1575
|
+
const withoutComments2 = stripJsComments(blankInlinedGsapLibrary(script.content));
|
|
1507
1576
|
const executable = stripStringLiterals(withoutComments2);
|
|
1508
1577
|
for (const { pattern, label, hint, scansStrings } of patterns) {
|
|
1509
1578
|
const match = pattern.exec(scansStrings ? withoutComments2 : executable);
|
|
@@ -1705,10 +1774,10 @@ function srcKind(src) {
|
|
|
1705
1774
|
} catch {
|
|
1706
1775
|
pathname = stripped.split("?")[0]?.split("#")[0] ?? stripped;
|
|
1707
1776
|
}
|
|
1708
|
-
const
|
|
1709
|
-
const dot =
|
|
1777
|
+
const base2 = pathname.split("/").pop() ?? "";
|
|
1778
|
+
const dot = base2.lastIndexOf(".");
|
|
1710
1779
|
if (dot < 0) return null;
|
|
1711
|
-
const ext =
|
|
1780
|
+
const ext = base2.slice(dot + 1).toLowerCase();
|
|
1712
1781
|
if (IMAGE_SRC_EXT.has(ext)) return "image";
|
|
1713
1782
|
if (VIDEO_SRC_EXT.has(ext)) return "video";
|
|
1714
1783
|
if (AUDIO_SRC_EXT.has(ext)) return "audio";
|
|
@@ -2503,7 +2572,7 @@ function findAudioGroupCarveAttrFindings(ctx) {
|
|
|
2503
2572
|
|
|
2504
2573
|
// src/scriptPositions.ts
|
|
2505
2574
|
import { parse as parse2 } from "acorn";
|
|
2506
|
-
import { simple } from "acorn-walk";
|
|
2575
|
+
import { simple as simple2 } from "acorn-walk";
|
|
2507
2576
|
var callIndexes = /* @__PURE__ */ new WeakMap();
|
|
2508
2577
|
function callsFor(script) {
|
|
2509
2578
|
const cached = callIndexes.get(script);
|
|
@@ -2515,7 +2584,7 @@ function callsFor(script) {
|
|
|
2515
2584
|
sourceType: "script",
|
|
2516
2585
|
allowReturnOutsideFunction: true
|
|
2517
2586
|
});
|
|
2518
|
-
|
|
2587
|
+
simple2(ast, {
|
|
2519
2588
|
CallExpression: (node) => {
|
|
2520
2589
|
calls.push(node);
|
|
2521
2590
|
}
|
|
@@ -4054,8 +4123,8 @@ function targetedSelectorTokens(selector) {
|
|
|
4054
4123
|
const compounds = group.trim().split(/[\s>+~]+/).filter(Boolean);
|
|
4055
4124
|
const last = compounds[compounds.length - 1];
|
|
4056
4125
|
if (!last) continue;
|
|
4057
|
-
const
|
|
4058
|
-
if (
|
|
4126
|
+
const simple4 = last.match(/[#.][A-Za-z0-9_-]+/g);
|
|
4127
|
+
if (simple4) for (const token of simple4) tokens.add(token);
|
|
4059
4128
|
}
|
|
4060
4129
|
return tokens;
|
|
4061
4130
|
}
|
|
@@ -6384,7 +6453,7 @@ var structureRules = [
|
|
|
6384
6453
|
|
|
6385
6454
|
// src/shaderDomains.ts
|
|
6386
6455
|
import { parse as parse3, parseExpressionAt } from "acorn";
|
|
6387
|
-
import { simple as
|
|
6456
|
+
import { simple as simple3 } from "acorn-walk";
|
|
6388
6457
|
function withoutComments(source) {
|
|
6389
6458
|
return source.replace(/\/\*[\s\S]*?\*\/|\/\/[^\r\n]*/g, (text) => text.replace(/[^\r\n]/g, " "));
|
|
6390
6459
|
}
|
|
@@ -6396,7 +6465,7 @@ function staticShaders(source) {
|
|
|
6396
6465
|
sourceType: "module",
|
|
6397
6466
|
allowReturnOutsideFunction: true
|
|
6398
6467
|
});
|
|
6399
|
-
|
|
6468
|
+
simple3(ast, {
|
|
6400
6469
|
Literal(node) {
|
|
6401
6470
|
if (typeof node.value !== "string") return;
|
|
6402
6471
|
shaders.push({
|
|
@@ -6443,8 +6512,8 @@ function zeroFlooredDot(a, b) {
|
|
|
6443
6512
|
}
|
|
6444
6513
|
function unsafeCosinePower(call) {
|
|
6445
6514
|
if (call.arguments.length !== 2) return false;
|
|
6446
|
-
const [
|
|
6447
|
-
return
|
|
6515
|
+
const [base2] = call.arguments;
|
|
6516
|
+
return base2?.type === "BinaryExpression" && base2.operator === "-" && base2.left.type !== "PrivateIdentifier" && isNumber(base2.left, 1) && unboundedCosine(base2.right);
|
|
6448
6517
|
}
|
|
6449
6518
|
function unsafePowOffsets(source) {
|
|
6450
6519
|
const offsets = [];
|
|
@@ -6452,7 +6521,7 @@ function unsafePowOffsets(source) {
|
|
|
6452
6521
|
for (const match of masked.matchAll(/\bpow\s*\(/g)) {
|
|
6453
6522
|
try {
|
|
6454
6523
|
const expression = parseExpressionAt(masked, match.index, { ecmaVersion: "latest" });
|
|
6455
|
-
|
|
6524
|
+
simple3(expression, {
|
|
6456
6525
|
CallExpression(node) {
|
|
6457
6526
|
if (node.start === match.index && unsafeCosinePower(node)) offsets.push(node.start);
|
|
6458
6527
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/lint",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.186",
|
|
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.186"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^25.0.10",
|