如何将序号添加到 google 文档中的非连续段落?

How do you add sequential numbers to non-contiguous paragraphs in a google doc?

在学术论文中,现象的例子通常放在它们自己的顺序编号的段落中。这些段落不一定彼此相邻,而是分散在整个文档中。这是一个示例文档,其中包含按顺序编号的段落,给出了当前主题的示例:

There are many languages, for example English (see example 1), Spanish (see example 2), Danish (see example 3).

(1) Google Docs are cool.
(2) Los documentos google son geniales.
(3) Google Dokumenter er seje.

Linguistics is the scientific study of languages, for example, Portuguese (see example 4):

(4) O português é bom.

Languages, human and computer, are fascinating.

我知道可以在 google 文档的光标处插入静态文本:

function insertHelloWorld() {
  var cursor = DocumentApp.getActiveDocument().getCursor();
  cursor.insertText("Hello World!");
}

我的问题: 如何在插入数字时跟踪数字,以便在使用现有示例将新示例插入文本中间时更新所有数字?因此,如果我要插入一个德语示例作为上面的数字 (2)(在英语和西班牙语示例之间),我想更新新插入的德语示例之后的示例编号:

...
(1) Google Docs are cool.
(2) Google Text & Tabellen sind cool.
(3) Los documentos google son geniales.
(4) Google Dokumenter er seje.
...
(5) O português é bom.
...

让“引用”成为“(参见示例 n)”字符串,其中 n 是一个数字。

让“示例”成为“(n) 示例文本...”,其中 n 是一个数字,它始终是一行的开头。

此解决方案假定您已手动订购“参考资料”和“示例”。该代码不会重新排序示例列表。因此,当前n值是多少并不重要,我们只需要遍历整个文档并应用序号即可。

如果您可以在 运行 更新时忘记所有格式设置,这将更容易实现。在这种情况下,您可以使用常规 JavaScript 并将 String.prototype.replace 应用于整个 body。但是,我假设您不想删除格式,因此我们不得不改用 DocumentApp 模型。

在我的示例中,我使用 body.findText 循环访问文档。不幸的是,这使用正则表达式 strings 而不是普通的 RegExp objects ,后者需要额外的反斜杠才能找到文字括号。此外,我使用 deleteTextinsertText 文本函数而不是 String.prototype.replace,因为使用 replace 将作用于整个元素,而不是 findText函数。

function updateSequentialReferences() {
  const body = DocumentApp.getActiveDocument().getBody();
  replaceSequentially(body, "\(see example \d+\)", count => `(see example ${count})`);
  replaceSequentially(body, "^\(\d+\)(.*)$", (count, match) => match.replace(/^\(\d+\)/, `(${count})`));
}

function replaceSequentially(body, regexString, replacerFn) {
  let foundRef = body.findText(regexString);
  let count = 1;
  while (foundRef !== null) {
    const {element, end, start} = unwrapRangeElement(foundRef);
    const text = element.asText();
    const match = text.getText().slice(start, end + 1);
    text.deleteText(start, end);
    text.insertText(start, replacerFn(count, match));
    ++count;
    foundRef = body.findText(regexString, foundRef);
  }
}

function unwrapRangeElement(element) {
  return {
    element: element.getElement(),
    end: element.getEndOffsetInclusive(),
    start: element.getStartOffset(),
  }
}