fix(web-probe): 对齐新版 MDTODO DOM 合同

This commit is contained in:
Codex
2026-07-13 14:23:05 +02:00
parent c5e8f163b5
commit cd7fb392f6
4 changed files with 114 additions and 28 deletions
@@ -3,6 +3,7 @@
export const MDTODO_TASK_TREE_PANE_CONTENT_SELECTOR = [
'[data-testid="mdtodo-task-tree-facts"]',
'[data-testid="mdtodo-task-page-fact"]',
"[data-task-ref]",
'[role="treeitem"]',
'[role="listitem"]',
@@ -433,22 +434,32 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
selected: option.selected === true,
})) : [];
const selectedFileOption = fileOptions.find((option) => option.selected) || null;
const taskItems = Array.from(document.querySelectorAll('[data-testid="mdtodo-task-tree"] [data-task-ref], [data-task-ref]')).filter(visible);
const taskCandidates = Array.from(document.querySelectorAll('[data-testid="mdtodo-task-tree"] li, [data-testid="mdtodo-task-tree"] [role="treeitem"], [data-testid="mdtodo-task-tree"] [role="listitem"]')).filter(visible);
const taskTree = document.querySelector('[data-testid="mdtodo-task-tree"]');
const semanticTaskCandidates = taskTree
? Array.from(taskTree.querySelectorAll('[role="treeitem"], [role="listitem"]')).filter(visible)
: [];
const fallbackTaskCandidates = taskTree
? Array.from(taskTree.querySelectorAll("li")).filter(visible)
: [];
const taskCandidates = semanticTaskCandidates.length > 0 ? semanticTaskCandidates : fallbackTaskCandidates;
const taskRefElement = (candidate) => candidate.matches("[data-task-ref]")
? candidate
: candidate.querySelector("[data-task-ref]");
const taskItems = Array.from(new Set(taskCandidates.map(taskRefElement).filter(visible)));
const selectedSource = document.querySelector('[data-source-id][data-selected="true"], [data-source-id][aria-selected="true"], [data-source-id].selected, [data-source-id].is-selected');
const selectedFile = document.querySelector('[data-file-ref][data-selected="true"], [data-file-ref][aria-selected="true"], [data-file-ref].selected, [data-file-ref].is-selected');
const selectedTask = document.querySelector('[data-task-ref][data-selected="true"], [data-task-ref][aria-selected="true"], [data-task-ref].selected, [data-task-ref].is-selected');
const statusCounts = {};
for (const task of taskItems) {
const status = task.getAttribute("data-task-status") || "unknown";
const status = task.getAttribute("data-task-status") || task.querySelector("[data-state]")?.getAttribute("data-state") || "unknown";
statusCounts[status] = (statusCounts[status] || 0) + 1;
}
const launch = document.querySelector('[data-testid="mdtodo-workbench-launch"], [data-action="launch-workbench"]');
const bodyRendered = document.querySelector('[data-testid="mdtodo-body-rendered"]');
const launch = document.querySelector('[data-testid="mdtodo-workbench-launch"], [data-testid="mdtodo-launch-workbench"], [data-action="launch-workbench"]');
const bodyRendered = document.querySelector('[data-testid="mdtodo-body-rendered"], [data-testid="mdtodo-body-read"]');
const reportPreview = document.querySelector('[data-testid="mdtodo-report-preview"]');
const reportFullscreen = document.querySelector('[data-testid="mdtodo-report-fullscreen-dialog"]');
const reportLinks = Array.from(document.querySelectorAll('[data-testid="mdtodo-report-link"]')).filter(visible);
const blockers = Array.from(document.querySelectorAll('[data-testid="mdtodo-workbench-launch-blocker"], [data-testid="mdtodo-workbench-launch-error"], [role="alert"]')).filter(visible).slice(0, 12).map((element, index) => ({
const blockers = Array.from(document.querySelectorAll('[data-testid="mdtodo-workbench-launch-blocker"], [data-testid="mdtodo-workbench-launch-error"], [data-testid="mdtodo-create-blocker"], .launch-blocker, [role="alert"]')).filter(visible).slice(0, 12).map((element, index) => ({
index,
testId: element.getAttribute("data-testid"),
role: element.getAttribute("role"),
@@ -475,7 +486,7 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
};
const paneGaps = [
measurePaneGap("task-tree", '[data-testid="mdtodo-task-tree"]', ${JSON.stringify(MDTODO_TASK_TREE_PANE_CONTENT_SELECTOR)}),
measurePaneGap("task-detail", '[data-testid="mdtodo-task-detail"]', '[data-testid="mdtodo-body-rendered"] > *, [data-testid="mdtodo-report-section"], [data-testid="mdtodo-workbench-launch"], [data-testid="mdtodo-delete-task"], [data-testid="mdtodo-task-detail-error"], .mdtodo-detail-header, .task-status-stack > *, .task-document-footer'),
measurePaneGap("task-detail", '[data-testid="mdtodo-task-detail"]', '[data-testid="mdtodo-body-rendered"] > *, [data-testid="mdtodo-body-read"], [data-testid="mdtodo-report-section"], [data-testid="mdtodo-workbench-launch"], [data-testid="mdtodo-launch-workbench"], [data-testid="mdtodo-delete-task"], [data-testid="mdtodo-task-detail-error"], .mdtodo-detail-header, .document-header, .task-status-stack > *, .task-document-footer, .document-footer'),
measurePaneGap("report-sidebar", '[data-testid="mdtodo-report-sidebar"]', '[data-testid="mdtodo-report-preview"] > *, [data-testid="mdtodo-report-error"], [data-testid="mdtodo-report-fullscreen"], [data-testid="mdtodo-report-close"], .report-sidebar-header, .report-preview .markdown-body > *'),
];
return {
@@ -486,17 +497,17 @@ async function sampleOnePage(targetPage, { reason, groupSeq, pageRole, targetPag
sourceCount: Math.max(sourceItems.length, sourceOptionCount),
fileCount: Math.max(fileItems.length, fileOptionCount),
taskCount: taskItems.length,
taskRefMissingCount: Math.max(0, taskCandidates.length - taskItems.length),
taskRefMissingCount: taskCandidates.filter((candidate) => !taskRefElement(candidate)).length,
selectedSourceId: opaqueDomId(selectedSource?.getAttribute("data-source-id") || sourceSelect?.value),
selectedFileRef: opaqueDomId(selectedFile?.getAttribute("data-file-ref") || fileSelect?.value),
selectedFileLabel: selectedFile ? trim(selectedFile.textContent || "", 180) : selectedFileOption?.label || null,
fileOptionLabels: fileOptions.map((option) => option.label).filter(Boolean).slice(0, 24),
selectedTaskRef: opaqueDomId(selectedTask?.getAttribute("data-task-ref")),
selectedTaskStatus: selectedTask?.getAttribute("data-task-status") || null,
selectedTaskStatus: selectedTask?.getAttribute("data-task-status") || selectedTask?.querySelector("[data-state]")?.getAttribute("data-state") || null,
sourceSelectVisible: visible(sourceSelect),
fileSelectVisible: visible(fileSelect),
sourceConfigVisible: visible(document.querySelector('[data-testid="mdtodo-source-form-hwpod"], [data-testid="mdtodo-source-config-dialog"], [role="dialog"]')),
taskEditorVisible: visible(document.querySelector('[data-testid="mdtodo-edit-title"], [data-testid="mdtodo-edit-body"]')),
taskEditorVisible: visible(document.querySelector('[data-testid="mdtodo-edit-title"], [data-testid="mdtodo-edit-body"], [data-testid="mdtodo-body-editor"]')),
taskBodyVisible: visible(bodyRendered),
taskBodyText: visible(bodyRendered) ? trim(bodyRendered.textContent || "", 500) : "",
newTaskDraftVisible: visible(document.querySelector('[data-testid="mdtodo-new-title"], [data-testid="mdtodo-new-body"]')),