745e9b691d
Memind CI / Test, build, and release guards (pull_request) Successful in 3m35s
未点公开发布但已落盘到 public/ 的页面,在无在线非 public 发布阻挡时 合成 implicit public snapshot,注入 canonical/JSON-LD 并扫描进 sitemap。 Co-authored-by: Cursor <cursoragent@cursor.com>
142 lines
4.6 KiB
JavaScript
142 lines
4.6 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
import {
|
|
dedupeDiscoveryEntriesByPage,
|
|
listWorkspacePublicHtmlIndexEntries,
|
|
mergeDiscoveryEntries,
|
|
renderLlmsTxt,
|
|
renderRobotsTxt,
|
|
renderSitemapXml,
|
|
resolveWorkspacePublicationIndexSnapshot,
|
|
} from './mindspace-seo-discovery-service.mjs';
|
|
|
|
test('renderSitemapXml emits only provided urls', () => {
|
|
const xml = renderSitemapXml(
|
|
[{ publicUrl: '/u/john/pages/demo', updatedAt: Date.parse('2026-08-01T00:00:00.000Z') }],
|
|
{ origin: 'https://m.tkmind.cn' },
|
|
);
|
|
assert.match(xml, /<loc>https:\/\/m\.tkmind\.cn\/u\/john\/pages\/demo<\/loc>/);
|
|
});
|
|
|
|
test('renderRobotsTxt references sitemap when enabled', () => {
|
|
const body = renderRobotsTxt({
|
|
origin: 'https://m.tkmind.cn',
|
|
sitemapEnabled: true,
|
|
llmsTxtEnabled: true,
|
|
});
|
|
assert.match(body, /Sitemap: https:\/\/m\.tkmind\.cn\/sitemap\.xml/);
|
|
assert.match(body, /llms\.txt/);
|
|
});
|
|
|
|
test('dedupeDiscoveryEntriesByPage prefers /u/ urls for the same page', () => {
|
|
const merged = dedupeDiscoveryEntriesByPage([
|
|
{
|
|
pageId: 'page-1',
|
|
publicUrl: '/MindSpace/user/public/demo.html',
|
|
accessMode: 'public',
|
|
status: 'online',
|
|
},
|
|
{
|
|
pageId: 'page-1',
|
|
publicUrl: '/u/john/pages/demo',
|
|
accessMode: 'public',
|
|
status: 'online',
|
|
},
|
|
]);
|
|
assert.equal(merged.length, 1);
|
|
assert.equal(merged[0].publicUrl, '/u/john/pages/demo');
|
|
});
|
|
|
|
test('dedupeDiscoveryEntriesByPage drops archived duplicates', () => {
|
|
const merged = dedupeDiscoveryEntriesByPage([
|
|
{
|
|
pageId: 'page-2',
|
|
publicUrl: '/MindSpace/user/public/_archived-demo.html',
|
|
accessMode: 'public',
|
|
status: 'online',
|
|
},
|
|
{
|
|
pageId: 'page-2',
|
|
publicUrl: '/u/john/pages/demo',
|
|
accessMode: 'public',
|
|
status: 'online',
|
|
},
|
|
]);
|
|
assert.equal(merged.length, 1);
|
|
assert.equal(merged[0].publicUrl, '/u/john/pages/demo');
|
|
});
|
|
|
|
test('mergeDiscoveryEntries appends platform static pages', () => {
|
|
const merged = mergeDiscoveryEntries([
|
|
{ publicUrl: '/u/john/pages/demo', accessMode: 'public', status: 'online' },
|
|
]);
|
|
assert.ok(merged.some((entry) => String(entry.publicUrl ?? '').includes('/learn/')));
|
|
});
|
|
|
|
test('renderLlmsTxt lists markdown links', () => {
|
|
const body = renderLlmsTxt(
|
|
[{ publicUrl: '/u/john/pages/demo', summary: '仙居玩水' }],
|
|
{ origin: 'https://m.tkmind.cn' },
|
|
);
|
|
assert.match(body, /\[仙居玩水\]\(https:\/\/m\.tkmind\.cn\/u\/john\/pages\/demo\)/);
|
|
});
|
|
|
|
test('listWorkspacePublicHtmlIndexEntries includes unpublished public html on disk', async () => {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'mindspace-seo-disk-'));
|
|
const userId = 'user-implicit-seo';
|
|
const publicDir = path.join(root, 'MindSpace', userId, 'public');
|
|
fs.mkdirSync(publicDir, { recursive: true });
|
|
fs.writeFileSync(
|
|
path.join(publicDir, 'weather-broadcast-20260916.html'),
|
|
'<!doctype html><html><head><title>Weather</title></head><body></body></html>',
|
|
'utf8',
|
|
);
|
|
|
|
const entries = await listWorkspacePublicHtmlIndexEntries(null, { h5Root: root });
|
|
assert.equal(entries.length, 1);
|
|
assert.match(entries[0].publicUrl ?? '', /weather-broadcast-20260916\.html/);
|
|
});
|
|
|
|
test('resolveWorkspacePublicationIndexSnapshot falls back to implicit public html', async () => {
|
|
const snapshot = await resolveWorkspacePublicationIndexSnapshot(null, {
|
|
userId: 'user-1',
|
|
workspaceRelativePath: 'public/demo.html',
|
|
publicUrl: 'https://m.tkmind.cn/MindSpace/user-1/public/demo.html',
|
|
});
|
|
assert.equal(snapshot?.accessMode, 'public');
|
|
assert.equal(snapshot?.status, 'online');
|
|
});
|
|
|
|
test('resolveWorkspacePublicationIndexSnapshot respects online non-public publication', async () => {
|
|
const pool = {
|
|
async query(sql, params) {
|
|
if (/access_mode <> 'public'/i.test(sql)) {
|
|
assert.equal(params[1], 'public/demo.html');
|
|
return [[{
|
|
id: 'pub-private',
|
|
page_id: 'page-1',
|
|
public_url: '/u/user/pages/demo',
|
|
access_mode: 'password',
|
|
status: 'online',
|
|
user_confirmed_at: null,
|
|
expires_at: null,
|
|
updated_at: Date.now(),
|
|
published_at: Date.now(),
|
|
title: 'Demo',
|
|
summary: '私有',
|
|
}]];
|
|
}
|
|
return [[], []];
|
|
},
|
|
};
|
|
const snapshot = await resolveWorkspacePublicationIndexSnapshot(pool, {
|
|
userId: 'user-1',
|
|
workspaceRelativePath: 'public/demo.html',
|
|
publicUrl: 'https://m.tkmind.cn/MindSpace/user-1/public/demo.html',
|
|
});
|
|
assert.equal(snapshot?.accessMode, 'password');
|
|
});
|