[英]How do I send a large amount of text into a contenteditable="true" element?
UPDATE:更新:
After some more research, I realized I can ask this question in a more specific manner: How do I send a large amount of text into a contenteditable="true"
element?经过更多研究,我意识到我可以以更具体的方式提出这个问题:如何将大量文本发送到
contenteditable="true"
元素中?
I am working with a website that has an API but it doesn't have any endpoints that can edit content.我正在使用一个具有 API 的网站,但它没有任何可以编辑内容的端点。 This API limitation prevents my release process from being automated.
这个 API 限制阻止了我的发布过程自动化。 As a workaround, I've tried to automate the tasks with a headless browser.
作为一种解决方法,我尝试使用无头浏览器自动执行任务。
One of these tasks involves editing the content in a rich text editor.其中一项任务涉及在富文本编辑器中编辑内容。 This rich text editor does not have any
input
elements, so this isn't as simple as changing the value of something.这个富文本编辑器没有任何
input
元素,所以这不像改变某些东西的值那么简单。 The HTML looks similar to this: HTML 看起来类似于:
You can look at the source of this rich text editor here: https://www.slatejs.org/examples/richtext您可以在此处查看此富文本编辑器的来源: https : //www.slatejs.org/examples/richtext
I've tried using some puppeteer code (I don't care if the solution to this answer is puppeteer or not) to solve this problem.我已经尝试使用一些 puppeteer 代码(我不在乎这个答案的解决方案是否是 puppeteer)来解决这个问题。 It works, but it's far too slow: I've got 30k of text to send to the editor, so
await page.keyboard.type(stdin, {delay: 0});
它有效,但太慢了:我有 30k 的文本要发送给编辑器,所以
await page.keyboard.type(stdin, {delay: 0});
takes well over ten minutes to run.运行需要十多分钟。 Here is my code:
这是我的代码:
export const edit = async () => {
const browser = await launch({ headless: false });
const page = await browser.newPage();
try {
await page.setUserAgent(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0'
);
await page.goto('https://www.slatejs.org/examples/richtext');
await page.waitForSelector('[data-slate-string="true"]');
await page.click('[data-slate-string="true"]');
// select all
await page.keyboard.down('Control');
await page.keyboard.press('a');
await page.keyboard.up('Control');
// clear everything in the rich text editor
await page.keyboard.press('Backspace');
// type in new content
await page.keyboard.type(aLargeAmountOfText, {delay: 0}); // this takes over 10 minutes!
} finally {
await page.screenshot({ path: 'example.png' });
await browser.close();
}
};
One thing that would work (in theory), is to automate copying and pasting the text into the editor.将工作(理论上)有一两件事,是自动复制和粘贴文本到编辑器。 I really don't want to go down this path, because I tend to do other things while I release.
我真的不想走这条路,因为我在释放时倾向于做其他事情。 If my script modifies my clipboard (or I modify it) while it's running, it could have unpredictable results.
如果我的脚本在运行时修改了我的剪贴板(或者我修改了它),它可能会产生不可预测的结果。
What's the quickest way of sending a large amount of text to a rich text editor that has no input
elements?将大量文本发送到没有
input
元素的富文本编辑器的最快方法是什么? I don't care what automation tool is used (I'd prefer node.js, if possible), or what tricks I have to use, so long as I can figure out how to answer this question.我不在乎使用什么自动化工具(如果可能,我更喜欢 node.js),或者我必须使用什么技巧,只要我能弄清楚如何回答这个问题。
You might try it with page.$eval :你可以用page.$eval试试:
export const edit = async () => {
const browser = await launch({ headless: false });
const page = await browser.newPage();
try {
await page.setUserAgent(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0'
);
await page.goto('https://www.slatejs.org/examples/richtext');
await page.waitForSelector('[contenteditable="true"]');
await page.$eval('[contenteditable="true"]', (e) => e.textContent = aLargeAmountOfText);
} finally {
await page.screenshot({ path: 'example.png' });
await browser.close();
}
};
OK, this was so hard to figure out. OK,这是那么很难搞清楚。 Here it is:
这里是:
await page.goto(url);
const richTextEditorSelector = '[contenteditable="true"]';
await page.waitForSelector(richTextEditorSelector);
await page.focus(richTextEditorSelector);
// select all
await page.evaluate(() => {
return Promise.resolve(document.execCommand('selectAll'));
});
const pasteReplacementText = `
const dataTransfer = new DataTransfer();
function dispatchPaste(target) {
// this may be 'text/html' if it's required
dataTransfer.setData('text/plain', \`${replacementText}\`);
target.dispatchEvent(
new ClipboardEvent('paste', {
clipboardData: dataTransfer,
// need these for the event to reach Draft paste handler
bubbles: true,
cancelable: true
})
);
// clear DataTransfer Data
dataTransfer.clearData();
}
dispatchPaste(document.querySelectorAll('${richTextEditorSelector}')[0]);
`;
console.log(`replacementText=
${pasteReplacementText}`); // leaving this here because it may help others troubleshoot
await page.evaluate(pasteReplacementText);
That complex string tricks the editor into thinking a paste occurred.那个复杂的字符串使编辑器认为发生了粘贴。 You supply the data.
您提供数据。
Here are some of the sources I used to come up with this:以下是我曾经提出的一些来源:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.