fix: update version to 0.5.3 and enhance placeholder selection logic in publishArticle function

This commit is contained in:
Jim Liu 宝玉 2026-01-17 01:29:10 -06:00
parent 6194f71378
commit fa155da15d
2 changed files with 99 additions and 42 deletions

View File

@ -6,7 +6,7 @@
}, },
"metadata": { "metadata": {
"description": "Skills shared by Baoyu for improving daily work efficiency", "description": "Skills shared by Baoyu for improving daily work efficiency",
"version": "0.5.2" "version": "0.5.3"
}, },
"plugins": [ "plugins": [
{ {

View File

@ -481,52 +481,78 @@ export async function publishArticle(options: ArticleOptions): Promise<void> {
const img = sortedImages[i]!; const img = sortedImages[i]!;
console.log(`[x-article] [${i + 1}/${sortedImages.length}] Inserting image at placeholder: ${img.placeholder}`); console.log(`[x-article] [${i + 1}/${sortedImages.length}] Inserting image at placeholder: ${img.placeholder}`);
// Find, scroll to, and select the placeholder text in DraftEditor // Helper to select placeholder with retry
const placeholderFound = await cdp.send<{ result: { value: boolean } }>('Runtime.evaluate', { const selectPlaceholder = async (maxRetries = 3): Promise<boolean> => {
expression: `(() => { for (let attempt = 1; attempt <= maxRetries; attempt++) {
const editor = document.querySelector('.DraftEditor-editorContainer [data-contents="true"]'); // Find, scroll to, and select the placeholder text in DraftEditor
if (!editor) return false; await cdp!.send('Runtime.evaluate', {
expression: `(() => {
const editor = document.querySelector('.DraftEditor-editorContainer [data-contents="true"]');
if (!editor) return false;
const placeholder = ${JSON.stringify(img.placeholder)}; const placeholder = ${JSON.stringify(img.placeholder)};
// Search through all text nodes in the editor // Search through all text nodes in the editor
const walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT, null, false); const walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT, null, false);
let node; let node;
while ((node = walker.nextNode())) { while ((node = walker.nextNode())) {
const text = node.textContent || ''; const text = node.textContent || '';
const idx = text.indexOf(placeholder); const idx = text.indexOf(placeholder);
if (idx !== -1) { if (idx !== -1) {
// Found the placeholder - scroll to it first // Found the placeholder - scroll to it first
const parentElement = node.parentElement; const parentElement = node.parentElement;
if (parentElement) { if (parentElement) {
parentElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); parentElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
// Select it
const range = document.createRange();
range.setStart(node, idx);
range.setEnd(node, idx + placeholder.length);
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
return true;
}
} }
return false;
})()`,
}, { sessionId });
// Select it // Wait for scroll and selection to settle
const range = document.createRange(); await sleep(800);
range.setStart(node, idx);
range.setEnd(node, idx + placeholder.length); // Verify selection matches the placeholder
const sel = window.getSelection(); const selectionCheck = await cdp!.send<{ result: { value: string } }>('Runtime.evaluate', {
sel.removeAllRanges(); expression: `window.getSelection()?.toString() || ''`,
sel.addRange(range); returnByValue: true,
return true; }, { sessionId });
}
const selectedText = selectionCheck.result.value.trim();
if (selectedText === img.placeholder) {
console.log(`[x-article] Selection verified: "${selectedText}"`);
return true;
} }
return false;
})()`,
returnByValue: true,
}, { sessionId });
// Wait for scroll animation if (attempt < maxRetries) {
await sleep(500); console.log(`[x-article] Selection attempt ${attempt} got "${selectedText}", retrying...`);
await sleep(500);
} else {
console.warn(`[x-article] Selection failed after ${maxRetries} attempts, got: "${selectedText}"`);
}
}
return false;
};
if (!placeholderFound.result.value) { // Try to select the placeholder
console.warn(`[x-article] Placeholder not found in DOM: ${img.placeholder}`); const selected = await selectPlaceholder(3);
if (!selected) {
console.warn(`[x-article] Skipping image - could not select placeholder: ${img.placeholder}`);
continue; continue;
} }
console.log(`[x-article] Placeholder selected, copying image: ${path.basename(img.localPath)}`); console.log(`[x-article] Copying image: ${path.basename(img.localPath)}`);
// Copy image to clipboard // Copy image to clipboard
if (!copyImageToClipboard(img.localPath)) { if (!copyImageToClipboard(img.localPath)) {
@ -535,17 +561,48 @@ export async function publishArticle(options: ArticleOptions): Promise<void> {
} }
// Wait for clipboard to be fully ready // Wait for clipboard to be fully ready
await sleep(800); await sleep(1000);
// Delete placeholder by pressing Enter (placeholder is already selected) // Delete placeholder by pressing Backspace (more reliable than Enter for replacing selection)
console.log(`[x-article] Deleting placeholder with Enter...`); console.log(`[x-article] Deleting placeholder...`);
await cdp.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13 }, { sessionId }); await cdp.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Backspace', code: 'Backspace', windowsVirtualKeyCode: 8 }, { sessionId });
await cdp.send('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13 }, { sessionId }); await cdp.send('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Backspace', code: 'Backspace', windowsVirtualKeyCode: 8 }, { sessionId });
// Wait and verify placeholder is deleted
await sleep(500);
// Check that placeholder is no longer in editor
const afterDelete = await cdp.send<{ result: { value: boolean } }>('Runtime.evaluate', {
expression: `(() => {
const editor = document.querySelector('.DraftEditor-editorContainer [data-contents="true"]');
if (!editor) return true;
return !editor.innerText.includes(${JSON.stringify(img.placeholder)});
})()`,
returnByValue: true,
}, { sessionId });
if (!afterDelete.result.value) {
console.warn(`[x-article] Placeholder may not have been deleted, trying again...`);
// Try selecting and deleting again
await selectPlaceholder(1);
await sleep(300);
await cdp.send('Input.dispatchKeyEvent', { type: 'keyDown', key: 'Backspace', code: 'Backspace', windowsVirtualKeyCode: 8 }, { sessionId });
await cdp.send('Input.dispatchKeyEvent', { type: 'keyUp', key: 'Backspace', code: 'Backspace', windowsVirtualKeyCode: 8 }, { sessionId });
await sleep(500);
}
// Focus editor to ensure cursor is in position
await cdp.send('Runtime.evaluate', {
expression: `(() => {
const editor = document.querySelector('.DraftEditor-editorContainer [contenteditable="true"]');
if (editor) editor.focus();
})()`,
}, { sessionId });
await sleep(300); await sleep(300);
// Paste image using paste script (activates Chrome, sends real keystroke) // Paste image using paste script (activates Chrome, sends real keystroke)
console.log(`[x-article] Pasting image...`); console.log(`[x-article] Pasting image...`);
if (pasteFromClipboard('Google Chrome', 5, 800)) { if (pasteFromClipboard('Google Chrome', 5, 1000)) {
console.log(`[x-article] Image pasted: ${path.basename(img.localPath)}`); console.log(`[x-article] Image pasted: ${path.basename(img.localPath)}`);
} else { } else {
console.warn(`[x-article] Failed to paste image after retries`); console.warn(`[x-article] Failed to paste image after retries`);