Initial k1412 research blog
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { access, readFile, readdir } from "node:fs/promises";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { join } from "node:path";
|
||||
|
||||
const root = new URL("../", import.meta.url);
|
||||
const contentRoot = new URL("../content/", import.meta.url);
|
||||
const required = ["title", "summary", "date", "updated", "topic", "kind", "status", "visibility", "canonicalUrl"];
|
||||
const forbidden = [
|
||||
[/\/(?:Users|home|mnt)\/[^\s)\]>'"]+/, "private absolute path"],
|
||||
[/\b(?:10\.(?:\d{1,3}\.){2}\d{1,3}|192\.168\.(?:\d{1,3}\.)\d{1,3}|100\.(?:6[4-9]|[7-9]\d|1[01]\d|12[0-7])\.(?:\d{1,3}\.)\d{1,3})\b/, "private IPv4"],
|
||||
[/(?:git\.n\.xiaomi\.com|coro\.doc|\.codex\/sessions|<codex_internal_context)/, "internal material"],
|
||||
[/-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/, "private key"],
|
||||
[/"?sourcePaths"?\s*:/, "Knowledge Hub private metadata"]
|
||||
];
|
||||
|
||||
async function files(dir) {
|
||||
const entries = await readdir(dir, { withFileTypes: true });
|
||||
const base = fileURLToPath(dir);
|
||||
return entries.flatMap((entry) => entry.isFile() && entry.name.endsWith(".md") ? [join(base, entry.name)] : []);
|
||||
}
|
||||
|
||||
function parse(text, path) {
|
||||
const match = text.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
||||
if (!match) throw new Error(`${path}: invalid frontmatter delimiters`);
|
||||
return { data: JSON.parse(match[1]), body: match[2].trim() };
|
||||
}
|
||||
|
||||
const paths = [...await files(new URL("posts/", contentRoot)), ...await files(new URL("sites/", contentRoot))];
|
||||
const errors = [];
|
||||
const urls = new Set();
|
||||
for (const path of paths) {
|
||||
const text = await readFile(path, "utf8");
|
||||
let parsed;
|
||||
try { parsed = parse(text, path); } catch (error) { errors.push(error.message); continue; }
|
||||
for (const key of required) if (!parsed.data[key]) errors.push(`${path}: missing ${key}`);
|
||||
if (parsed.data.visibility !== "public") errors.push(`${path}: visibility must be public`);
|
||||
if (!/^https:\/\//.test(parsed.data.canonicalUrl ?? "")) errors.push(`${path}: canonicalUrl must use HTTPS`);
|
||||
if (urls.has(parsed.data.canonicalUrl)) errors.push(`${path}: duplicate canonicalUrl`);
|
||||
urls.add(parsed.data.canonicalUrl);
|
||||
if (parsed.data.kind === "article" && !parsed.body) errors.push(`${path}: empty article body`);
|
||||
if (parsed.data.preview?.startsWith("/")) {
|
||||
try { await access(new URL(`../public${parsed.data.preview}`, import.meta.url)); }
|
||||
catch { errors.push(`${path}: missing preview asset ${parsed.data.preview}`); }
|
||||
}
|
||||
for (const [pattern, label] of forbidden) if (pattern.test(text)) errors.push(`${path}: forbidden ${label}`);
|
||||
}
|
||||
if (errors.length) {
|
||||
console.error(errors.join("\n"));
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`valid: ${paths.length} public content entries at ${root.pathname}`);
|
||||
Reference in New Issue
Block a user