源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { existsSync, readFileSync } from "node:fs";
|
||||
import { dirname, join, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import {
|
||||
analyzeCssHasPerformance,
|
||||
isCssHasPerformancePath
|
||||
} from "./css-has-performance-policy.mjs";
|
||||
|
||||
const scriptDirectory = dirname(fileURLToPath(import.meta.url));
|
||||
const workspaceRoot = resolve(scriptDirectory, "../..");
|
||||
const staged = process.argv.includes("--staged");
|
||||
const files = listFiles();
|
||||
const diagnostics = files.flatMap((path) =>
|
||||
analyzeCssHasPerformance({ path, source: readSource(path) })
|
||||
);
|
||||
|
||||
if (diagnostics.length > 0) {
|
||||
console.error(
|
||||
":has() is forbidden on large dynamic CSS subjects because descendant mutations can invalidate the full subject subtree."
|
||||
);
|
||||
for (const diagnostic of diagnostics) {
|
||||
console.error(
|
||||
`- ${diagnostic.path}:${diagnostic.line}:${diagnostic.column} ${diagnostic.selector}: ${diagnostic.message}`
|
||||
);
|
||||
}
|
||||
process.exitCode = 1;
|
||||
} else {
|
||||
console.log(
|
||||
`CSS :has() performance policy passed (${files.length} ${staged ? "staged " : ""}files)`
|
||||
);
|
||||
}
|
||||
|
||||
function listFiles() {
|
||||
const args = staged
|
||||
? ["diff", "--cached", "--name-only", "--diff-filter=ACMR", "-z"]
|
||||
: ["ls-files", "--cached", "--others", "--exclude-standard", "-z"];
|
||||
return execFileSync("git", args, {
|
||||
cwd: workspaceRoot,
|
||||
encoding: "utf8"
|
||||
})
|
||||
.split("\0")
|
||||
.filter(Boolean)
|
||||
.map((path) => path.replaceAll("\\", "/"))
|
||||
.filter(isCssHasPerformancePath)
|
||||
.filter((path) => staged || existsSync(join(workspaceRoot, path)));
|
||||
}
|
||||
|
||||
function readSource(path) {
|
||||
if (staged) {
|
||||
return execFileSync("git", ["show", `:${path}`], {
|
||||
cwd: workspaceRoot,
|
||||
encoding: "utf8",
|
||||
maxBuffer: 20 * 1024 * 1024
|
||||
});
|
||||
}
|
||||
return readFileSync(join(workspaceRoot, path), "utf8");
|
||||
}
|
||||
Reference in New Issue
Block a user