Files
memind/scripts/check-mindspace-cover.mjs
T
john 357e26ab49
Memind CI / Test, build, and release guards (pull_request) Failing after 7m12s
Memind CI / Test, build, and release guards (push) Has been cancelled
feat(seo-geo): 落盘自动补齐与 143 全量回填支持
Finish/交付写盘前自动回填 mindspace-geo,扩展 storage publications 扫描与 geo meta 解析,并增加 143 生产回填脚本。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 10:26:02 +08:00

111 lines
3.6 KiB
JavaScript

#!/usr/bin/env node
/**
* Scan HTML pages for mindspace-cover + SEO/GEO compliance.
*
* Usage:
* node scripts/check-mindspace-cover.mjs
* node scripts/check-mindspace-cover.mjs --scope all
* node scripts/check-mindspace-cover.mjs --user <uuid>
* node scripts/check-mindspace-cover.mjs --file public/thumbnail-demo-samples/vietnam-guide-good.html
*/
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import {
auditHtmlFile,
collectHtmlTargets,
} from '../mindspace-seo-audit.mjs';
const repoRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
const DEFAULT_PUBLISH_ROOT = 'MindSpace';
function parseArgs(argv) {
let scope = 'all';
let root = path.join(repoRoot, DEFAULT_PUBLISH_ROOT);
let publicRoot = path.join(repoRoot, 'public');
let storageRoot = null;
let userId = null;
let file = null;
let seo = true;
for (let i = 2; i < argv.length; i += 1) {
if (argv[i] === '--scope' && argv[i + 1]) {
scope = argv[i + 1];
i += 1;
} else if (argv[i] === '--root' && argv[i + 1]) {
root = path.resolve(argv[i + 1]);
i += 1;
} else if (argv[i] === '--public-root' && argv[i + 1]) {
publicRoot = path.resolve(argv[i + 1]);
i += 1;
} else if (argv[i] === '--storage-root' && argv[i + 1]) {
storageRoot = path.resolve(argv[i + 1]);
i += 1;
} else if (argv[i] === '--user' && argv[i + 1]) {
userId = argv[i + 1];
i += 1;
} else if (argv[i] === '--file' && argv[i + 1]) {
file = path.resolve(argv[i + 1]);
i += 1;
} else if (argv[i] === '--seo') {
seo = true;
} else if (argv[i] === '--skip-seo') {
seo = false;
} else if (argv[i] === '--help' || argv[i] === '-h') {
console.log(`Usage: node scripts/check-mindspace-cover.mjs [--scope mindspace|platform|all] [--root ${DEFAULT_PUBLISH_ROOT}] [--user <uuid>] [--file <html>] [--skip-seo]`);
process.exit(0);
}
}
return { scope, root, publicRoot, storageRoot, userId, file, seo };
}
function isPlatformOnlyPath(htmlPath, publicRoot) {
const resolvedPublicRoot = path.resolve(publicRoot);
const resolved = path.resolve(htmlPath);
return resolved.startsWith(`${resolvedPublicRoot}${path.sep}`);
}
const { scope, root, publicRoot, storageRoot, userId, file, seo } = parseArgs(process.argv);
const targets = collectHtmlTargets({
scope,
mindspaceRoot: root,
publicRoot,
storageRoot,
userId,
file,
});
const results = [];
for (const htmlPath of targets) {
const html = fs.readFileSync(htmlPath, 'utf8');
const platformOnly = isPlatformOnlyPath(htmlPath, publicRoot);
const issues = auditHtmlFile(htmlPath, html, {
seo,
requireCoverMeta: !platformOnly,
});
if (issues.length) {
results.push({ htmlPath, issues });
}
}
if (results.length === 0) {
const scopeLabel = file ?? `${scope} @ ${root}${userId ? ` (user ${userId})` : ''}`;
console.log(`OK: ${targets.length} 个 HTML 页面均符合 mindspace-cover + SEO/GEO 规范 (${scopeLabel})`);
process.exit(0);
}
let errors = 0;
let warns = 0;
console.error(`Found cover/SEO issues in ${results.length} / ${targets.length} HTML files:`);
for (const { htmlPath, issues } of results) {
const rel = file ? htmlPath : path.relative(repoRoot, htmlPath);
console.error(`\n${rel}`);
for (const issue of issues) {
const prefix = issue.level === 'error' ? ' ✗' : ' ⚠';
console.error(`${prefix} [${issue.code}] ${issue.message}`);
if (issue.level === 'error') errors += 1;
else warns += 1;
}
}
console.error(`\n合计: ${errors} 错误, ${warns} 警告`);
process.exit(errors > 0 ? 1 : 0);