import fs from 'node:fs';
import { artifactFileExists } from './page-artifact.mjs';
import { hasPlatformBrandMarker } from '../../mindspace-page-tag.mjs';
export { hasPlatformBrandMarker };
const RASTER_IMAGE_PATTERN = /\.(png|jpe?g|webp|gif)(?:[?#]|$)/i;
export function hasMindspaceCoverMeta(html) {
return /]*name=["']mindspace-cover["']/i.test(String(html ?? ''));
}
export function hasShareDescription(html) {
const source = String(html ?? '');
return (
/]+property=["']og:description["']/i.test(source) ||
/]+name=["']description["']/i.test(source)
);
}
export function hasRasterShareImageHint(html) {
const source = String(html ?? '');
if (/]+property=["']og:image["'][^>]+content=["'][^"']+/i.test(source)) {
const match =
source.match(/]+property=["']og:image["'][^>]+content=["']([^"']+)["']/i) ??
source.match(/]+content=["']([^"']+)["'][^>]+property=["']og:image["']/i);
const url = match?.[1] ?? '';
if (url && !/\.svg(?:[?#]|$)/i.test(url)) return true;
}
const coverMatch = source.match(/]*name=["']mindspace-cover["'][^>]*content=(["'])([\s\S]*?)\1/i);
if (!coverMatch?.[2]) return false;
try {
const meta = JSON.parse(coverMatch[2].replaceAll('"', '"'));
const cover = String(meta.cover ?? meta.image ?? '').trim();
if (!cover) return false;
if (/^https?:\/\//i.test(cover)) return RASTER_IMAGE_PATTERN.test(cover);
return RASTER_IMAGE_PATTERN.test(cover) || !/\.svg(?:[?#]|$)/i.test(cover);
} catch {
return false;
}
}
/**
* WeChat link cards need mindspace-cover (for thumbnail.png) + description.
* Visual pages should also reference a raster hero in cover/image when possible.
*/
export function verifySharePreviewMeta(html) {
if (!hasMindspaceCoverMeta(html)) {
return { ok: false, reason: 'missing_mindspace_cover' };
}
if (!hasShareDescription(html)) {
return { ok: false, reason: 'missing_description' };
}
if (!hasPlatformBrandMarker(html)) {
return { ok: false, reason: 'missing_platform_brand' };
}
return { ok: true, reason: null };
}
export function verifyArtifactSharePreview(artifact) {
if (!artifactFileExists(artifact)) {
return { ok: false, reason: 'missing_file' };
}
const content = fs.readFileSync(artifact.localPath, 'utf8');
return verifySharePreviewMeta(content);
}
export function filterSharePreviewReadyArtifacts(artifacts = []) {
return artifacts.filter((artifact) => verifyArtifactSharePreview(artifact).ok);
}