如何以编程方式实时更新 Google 文档(通过 Chrome 扩展程序或外部 JS)

Dru*_*uux 5 javascript google-api google-docs google-chrome-extension google-apps-script

我想通过 Google Chrome 扩展程序或简单的 JavaScript 在外部以编程方式编辑我的 Google Doc,并在 Google Doc 中实时(实时)查看更改。当这个问题出现时,我正在寻找可以编辑 Google 文档并以编程方式保存更改的 Chrome 扩展程序。在我的研究过程中,我遇到了Grammarly。他们如何近乎实时地将拼写更正应用到 Google Doc 中,这给我留下了深刻的印象。你可以像这样重现它:

  1. 安装Grammarly Chrome 扩展
  1. 打开/创建 Google 文档
  2. 让 Grammarly 检查您的文本(突出显示包含错误的单词)
  3. 左键单击突出显示的单词
  4. 单击建议的更正

然后 Grammarly 将更新 Google Doc。我注意到了什么:

  • Google Doc 似乎没有通过 Google Docs API 或 Google AppScript 更新
  • 当用户手动编辑文档时,保存过程的行为似乎与 Google 文档本身的官方自动保存机制相同。这可以解释如下:
    • 自动保存指示器被触发
      在此处输入图片说明
    • save执行Google Docs HTTP 请求
      HTTP FormData 还包含适当的参数组合(数组的第 1 个命令中定义的索引范围si(startIndex) 和ei(endIndex)内的现有单词被第 2 个命令中的新单词替换)
[{"commands":[{"ty":"ds","si":229,"ei":232}, {"ty":"is","ibi":229,"s":"Test"}]}]
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

我已经尝试了以下解决方案:

  1. 使用Google 文档 API
    结果: ?工作,但有长达 5 秒的明显延迟
gapi.client.docs.documents.batchUpdate({
    documented: <docId>,
    requests: [
        {
            deleteContentRange: {
                range: {
                    startIndex: 1,
                    endIndex: 10,
                },
            },
        },
        {
            insertText: {
                location: {
                    index: 1,
                },
                text: 'Lorem ipsum',
            },
        },
    ],
})
Run Code Online (Sandbox Code Playgroud)
  1. 使用Google Script API执行 AppScript 功能。
    结果: ?工作,但有长达 5 秒的明显延迟
// API call
await gapi.client.script.scripts.run({
    scriptId: <scriptId>,
    resource: {
        function: 'myFunction'
    }
})

// AppScript function from Google Script Editor
function myFunction() {
    var body = DocumentApp.openById(<docId>).getBody()
    body.appendParagraph("Lorem ipsum")
}
Run Code Online (Sandbox Code Playgroud)
  1. 直接在Google Doc中操作DOM(这里我尝试用JavaScript编辑Google Doc的文本然后保存)。
    结果: ?我找不到触发自动保存机制的方法
  2. 手动执行内部 Google Docs(自动)保存方法。
    结果: ?导致内部服务器错误

不幸的是,迄今为止所有的尝试都没有成功或没有达到预期的结果。

sci*_*boy 8

(此方法甚至适用于新的基于画布的渲染)

事实证明这非常简单;我们都想太多了。您只需使用事件模拟按键,然后使用 for 循环立即替换您需要修改的任何文本。但是,Google Docs 使用包含内容的 Iframe 来监听关键事件

<html>
    <head></head>
    <body spellcheck="false" role="textbox" aria-label="Document content" contenteditable="true" style="background-color: transparent;"></body>
</html>
Run Code Online (Sandbox Code Playgroud)

所以我们必须在 IFrame 而不是文档上触发事件。另外,内容脚本对我不起作用,因此我必须将另一个脚本注入页面并使用自定义事件告诉注入的脚本模拟按键。您可以按照此处所述注入脚本,然后,从注入的脚本中,您可以在文档上模拟按键,如下所示:

const keyEvent = document.createEvent('Event')
keyEvent.initEvent('keypress', true, true)
keyEvent.key = KEY // A key like 'a' or 'B' or 'Backspace'
  // You will need to change this line if you want to use other special characters such as the left and right arrows
keyEvent.keyCode = KEY.charCodeAt(0) 
document.querySelector('.docs-texteventtarget-iframe')
  .contentDocument.activeElement
  .dispatchEvent(keyEvent)
Run Code Online (Sandbox Code Playgroud)

(从这个答案获得)

您可以将上述代码包装在注入脚本的事件侦听器中,并从内容脚本中分派一个自定义事件(以 为键名),以触发如下所示的detail按键。

对于我的用例,我不关心光标在哪里,但是如果您需要找到光标在哪里,以便您可以知道模拟左/右键的次数,您可以通过计算长度轻松获得索引所有文本类并查找光标相对于每个字符的位置。我找到了一个很好的小库来执行此操作(尽管它有一些警告,因为 Google Docs 显然一次只加载一页),它太长,无法包含在此处,但您可以在 GitHub 上查看它

  • 也为我工作过!谢谢:)使用“keypress”而不是“keydown”很重要,尽管“keypress”已被弃用 (2认同)