简体   繁体   English

如何将大量文本发送到 contenteditable="true" 元素中?

[英]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:以下是我曾经提出的一些来源:

  1. https://stackoverflow.com/a/63643176/61624 https://stackoverflow.com/a/63643176/61624
  2. https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content
  3. https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent
  4. https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pageevaluatepagefunction-args https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#pageevaluatepagefunction-args
  5. https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 关于contenteditable = true元素的文本建议 - Text suggestions on a contenteditable=true element 如何使用Selenium和python将字符序列发送到contenteditable =“ true”元素 - How can i send character sequence to a contenteditable=“true” element by using selenium and python 如何从Web视图向objc发送大量文本? - How can I send a large amount of text from a webview to objc? 如何在单击元素时将contenteditable设置为true - How can I set the contenteditable true on clicking the element 使用ContentEditable =“true”在元素溢出时向左滚动文本 - Scroll Text Left on Overflow for Element with ContentEditable=“true” 如何从contentEditable div获取html进入隐藏文本表单元素? - How do I get the html from a contentEditable div to go inside of a hidden text form element? 如何使用contentEditable = true选择两个元素的文本? - How to select text of the two elements with contentEditable = true? 如何通过javascript将元素置于contenteditable模式 - How do I put an element into contenteditable mode via javascript 通过表单将大量文本发送到servlet - Send large amount of text to servlet via form 如何限制粘贴在 contenteditable 区域中的文本样式? - How do I restrict the style of the text pasted in a contenteditable area?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM