e64cf52f23
Finish-sync guards now accept SEO/GEO disk enrichment instead of requiring byte-identical HTML, and fragment writes no longer duplicate doctype. Users canary mode keeps the full native pool while routing allowlisted identities to :18015 without overriding memory settings. Co-authored-by: Cursor <cursoragent@cursor.com>
55 lines
2.3 KiB
JavaScript
55 lines
2.3 KiB
JavaScript
function escapeMetaAttribute(value) {
|
|
return String(value ?? '')
|
|
.replaceAll('&', '&')
|
|
.replaceAll('"', '"')
|
|
.replaceAll('<', '<');
|
|
}
|
|
|
|
export function parseMindspaceCoverMeta(html) {
|
|
const tag = String(html).match(/<meta[^>]*name=["']mindspace-cover["'][^>]*>/i)?.[0];
|
|
if (!tag) return null;
|
|
const contentMatch =
|
|
tag.match(/content=(["'])([\s\S]*?)\1/i) ?? tag.match(/content=["']([^"']+)["']/i);
|
|
const raw = contentMatch?.[2] ?? contentMatch?.[1];
|
|
if (!raw) return null;
|
|
try {
|
|
return JSON.parse(raw.replaceAll('"', '"'));
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function upsertMindspaceCoverMeta(html, coverMeta, { replace = false } = {}) {
|
|
const payload = replace
|
|
? { ...(coverMeta ?? {}) }
|
|
: { ...(parseMindspaceCoverMeta(html) ?? {}), ...(coverMeta ?? {}) };
|
|
const metaTag = `<meta name="mindspace-cover" content="${escapeMetaAttribute(JSON.stringify(payload))}">`;
|
|
const source = String(html ?? '');
|
|
|
|
if (/<meta[^>]*name=["']mindspace-cover["'][^>]*>/i.test(source)) {
|
|
return source.replace(/<meta[^>]*name=["']mindspace-cover["'][^>]*>/i, metaTag);
|
|
}
|
|
if (/<head[^>]*>/i.test(source)) {
|
|
return source.replace(/<head([^>]*)>/i, `<head$1>\n ${metaTag}`);
|
|
}
|
|
if (/<html[^>]*>/i.test(source)) {
|
|
return source.replace(/<html([^>]*)>/i, `<html$1><head>${metaTag}</head>`);
|
|
}
|
|
const body = source.replace(/^\s*<!doctype[^>]*>\s*/i, '');
|
|
return `<!doctype html><html lang="zh-CN"><head>${metaTag}</head><body>${body}</body></html>`;
|
|
}
|
|
|
|
export function normalizeCoverMetaSuggestion(raw) {
|
|
const payload = raw && typeof raw === 'object' ? raw : {};
|
|
const next = {};
|
|
if (payload.tag != null) next.tag = String(payload.tag).trim().slice(0, 12);
|
|
if (payload.emoji != null) next.emoji = String(payload.emoji).trim().slice(0, 4);
|
|
if (payload.accent != null) next.accent = String(payload.accent).trim();
|
|
if (payload.accent2 != null) next.accent2 = String(payload.accent2).trim();
|
|
if (payload.subtitle != null) next.subtitle = String(payload.subtitle).trim().slice(0, 80);
|
|
if (payload.cover != null) next.cover = String(payload.cover).trim().slice(0, 512);
|
|
if (payload.image != null && !next.cover) next.cover = String(payload.image).trim().slice(0, 512);
|
|
if (payload.mood != null) next.mood = String(payload.mood).trim().slice(0, 24);
|
|
return next;
|
|
}
|