fix local markdown attachment regressions

This commit is contained in:
lix-2026
2026-05-29 11:13:05 +08:00
parent 1109e3c0d8
commit cbe789e034
63 changed files with 3249 additions and 1502 deletions
@@ -106,6 +106,50 @@ async function waitForEditorLinks(page, expectedCount) {
})));
}
function assertStandardMarkdownAttachmentLinks(links, label) {
assert(links.length > 0, `${label}: 应存在编辑器附件链接`);
for (const link of links) {
assert(!link.href.includes("/office-preview"), `${label}: 附件 href 不应持久写入 /office-preview: ${JSON.stringify(link)}`);
assert(!link.href.includes("/api/local-folder/files/open"), `${label}: 附件 href 不应持久写入本地 open API: ${JSON.stringify(link)}`);
assert(/^(?:\.{1,2}\/|[^:/?#]+(?:\/|$))/.test(link.href), `${label}: 附件 href 应为 Markdown 相对链接: ${JSON.stringify(link)}`);
}
}
function assertMarkdownSourceUsesStandardAttachmentLinks(root, relativePath, label) {
const markdown = fs.readFileSync(path.join(root, relativePath), "utf8");
assert(!markdown.includes("/office-preview"), `${label}: Markdown 原文不应包含 /office-preview\n${markdown}`);
assert(!markdown.includes("/api/local-folder/files/open"), `${label}: Markdown 原文不应包含本地 open API\n${markdown}`);
assert(/\[[^\]]+\.pptx\]\(\.\/[^)]+\.pptx\)/i.test(markdown), `${label}: Markdown 原文应包含标准相对 PPTX 链接\n${markdown}`);
return markdown;
}
async function readPageAggregate(page) {
return await page.evaluate(() => {
const script = document.getElementById("__MNOTE_PAGE_AGGREGATE__");
if (!script) return null;
try {
return JSON.parse(script.textContent || "null");
} catch (_error) {
return null;
}
});
}
async function assertAttachmentRefProjection(page, expectedCount, label) {
const aggregate = await readPageAggregate(page);
const refs = Array.isArray(aggregate?.body?.attachmentRefs) ? aggregate.body.attachmentRefs : [];
assert(refs.length >= expectedCount, `${label}: attachmentRefs 数量不足: ${JSON.stringify(refs)}`);
const pptxRefs = refs.filter((ref) => /\.pptx$/i.test(String(ref.rawHref || "")));
assert(pptxRefs.length >= expectedCount, `${label}: attachmentRefs 应包含 PPTX: ${JSON.stringify(refs)}`);
for (const ref of pptxRefs.slice(0, expectedCount)) {
assert(/^\.\//.test(String(ref.rawHref || "")), `${label}: rawHref 应保持同目录 Markdown 相对链接: ${JSON.stringify(ref)}`);
assert.equal(ref.kind, "pageLocal", `${label}: 同目录附件应为 pageLocal: ${JSON.stringify(ref)}`);
assert.equal(ref.openKind, "office", `${label}: PPTX openKind 应为 office: ${JSON.stringify(ref)}`);
assert.equal(ref.authorized, true, `${label}: 当前授权 root 内附件应 authorized=true: ${JSON.stringify(ref)}`);
}
return pptxRefs;
}
async function assertNoConflict(page, label) {
await page.waitForTimeout(1500);
const state = await page.evaluate(() => {
@@ -403,23 +447,29 @@ async function main() {
await uploadAttachmentViaSlash(page, PPTX_PATH);
const firstLinks = await waitForEditorLinks(page, 1);
assertStandardMarkdownAttachmentLinks(firstLinks, "first-editor-upload");
const firstConflictState = await assertNoConflict(page, "first-editor-upload");
assertLocalUploadSaveVersions(result, 1);
result.states.push({ step: "first-editor-upload", links: firstLinks, conflictState: firstConflictState });
const firstMarkdown = assertMarkdownSourceUsesStandardAttachmentLinks(root, relativePath, "first-editor-upload");
result.states.push({ step: "first-editor-upload", links: firstLinks, conflictState: firstConflictState, markdown: firstMarkdown });
await typeLineAfterUpload(page, "第一份附件后的正文");
const afterFirstEditConflictState = await assertNoConflict(page, "after-first-upload-edit");
result.states.push({ step: "after-first-upload-edit", conflictState: afterFirstEditConflictState });
await uploadAttachmentViaSlash(page, PPTX_PATH);
const secondLinks = await waitForEditorLinks(page, 2);
assertStandardMarkdownAttachmentLinks(secondLinks, "second-editor-upload");
const secondConflictState = await assertNoConflict(page, "second-editor-upload");
assertLocalUploadSaveVersions(result, 2);
const secondMarkdown = assertMarkdownSourceUsesStandardAttachmentLinks(root, relativePath, "second-editor-upload");
await delay(1800);
const editorRows = await waitForFileTreeAssetRows(page, 2);
result.states.push({ step: "second-editor-upload", links: secondLinks, conflictState: secondConflictState, fileTreeRows: editorRows });
result.states.push({ step: "second-editor-upload", links: secondLinks, conflictState: secondConflictState, markdown: secondMarkdown, fileTreeRows: editorRows });
assert(editorRows.every((row) => row.localRelativePath), `文件树上传行缺少本地路径: ${JSON.stringify(editorRows)}`);
await openDocument(page, root, relativePath);
await waitForEditorLinks(page, 2);
assertStandardMarkdownAttachmentLinks(await waitForEditorLinks(page, 2), "reopen-editor-upload");
const attachmentRefs = await assertAttachmentRefProjection(page, 2, "reopen-editor-upload");
result.states.push({ step: "reopen-editor-upload", attachmentRefs });
await clickEditorPptxLink(page, context, fileName);
await activatePrimaryPageTab(page);
await clickEditorPptxLink(page, context, fileName.replace(/\.pptx$/i, "-1.pptx"));