← 提示词库 Anthropic/claude-code/skills/google-workspace/references/docs.md 原文 md
🌐 中英双语对照

Google Docs reference / Google Docs 参考指南

As a first step, before you create a Google Doc or change one, you must read the design rules below in full: how a document should look and read, and how to edit one. After them, "Applying the design rules" says how to carry out the rules with these tools, and the rest of the file covers the Docs connector's read_doc and update_doc and the Drive tools that help with Docs.

作为第一步,在创建或修改 Google 文档之前,你必须完整阅读下面的设计规则:文档应呈现何种外观与行文,以及如何编辑文档。读完规则后,"Applying the design rules"(应用设计规则)一节说明如何借助这些工具落实规则,本文件其余部分介绍 Docs 连接器的 read_doc 与 update_doc,以及配合 Docs 使用的 Drive 工具。

Document design / 文档设计

When the user asks for something specific, such as a font, a color, a length or a structure, do that; these rules decide what the user left open. The rules for the text itself are under Writing, and the rules for changing a document that already exists are under Editing an existing document.

当用户提出具体要求,例如字体、颜色、篇幅或结构时,照做即可;这些规则只决定用户未明确说明的部分。针对文本本身的规则见 Writing 一节,修改既有文档的规则见 Editing an existing document 一节。

Structure / 结构

Styles / 样式

The look of a document comes from its styles: the Normal text style for body text and the built-in heading styles for headings. Formatting set directly on individual paragraphs carries over into the text added after them and spreads across a long document.

文档的外观来自其样式:正文使用 Normal text 样式,标题使用内置标题样式。直接设置在单个段落上的格式会延续到其后新增的文本,并在长文档中蔓延。

Fonts / 字体

Lists and numbering / 列表与编号

Tables / 表格

Page layout / 页面布局

Check the result / 检查成果

Look at the rendered pages, not only the text. Assume there are formatting problems and look for them:

要查看渲染后的页面,不能只看文本。先假定存在格式问题,再逐项排查:

After you fix one problem, check the paragraphs and pages around it. A fix to one paragraph often changes the next one, and a change in length moves the page breaks.

修复一个问题后,检查其周边的段落和页面。对某段的修改常常影响下一段,篇幅变化也会移动分页位置。

Writing / 行文

Text you write in a document should read as though a person wrote it. When readers think something was written by AI, they judge it as sloppy and stop trusting it, whatever the content. They make that judgment from a set of common indicators, listed below, so take extra care to keep them out of your writing. These rules are for text you write, and a style the user or their style guide asks for takes priority. Do not rewrite the user's existing text to follow them unless the user asks you to.

文档中写出的文字应读起来像出自真人之手。读者一旦认定某段文字是 AI 写的,无论内容如何都会视之为草率并不再信任它。他们依据的是一组常见特征,列举如下,因此要格外注意不让这些特征出现在你的文字里。这些规则约束的是你写出的文本;用户或其风格指南指定的风格优先。除非用户要求,不要为套用这些规则而改写用户已有的文字。

【评论】该节把读者的 AI 文本识别特征显式列为禁用项,是对模型输出风格质量的工程化约束;同时明确用户或风格指南的优先级更高,避免规则与用户要求冲突。

Editing an existing document / 编辑既有文档

These rules apply whenever you change a document that already exists. Everything you add also follows the rules above.

只要你修改的是已存在的文档,这些规则就适用。你新增的一切内容同样遵循上文所有规则。

Change only what was asked / 只改要求之处

Match what is there / 与既有内容保持一致

Things inside the text / 文本内部的元素

Some elements sit inside a paragraph's text without looking like separate objects: footnote marks, chips (such as a person, date or file chip), bookmark boundaries, comment anchors, and inline images and charts. Replacing or deleting a range that contains one removes it: the footnote is gone, the chip is deleted, the bookmark moves, the chart disappears.

有些元素嵌在段落文本内部,看起来不像独立对象:脚注标记、智能片段(chip,如联系人、日期或文件 chip)、书签边界、评论锚点,以及行内图片和图表。替换或删除包含它们的范围会把它们一并删掉:脚注消失、chip 被删除、书签移位、图表不见。

Templates / 模板

Comments / 评论

Suggestions / 修订建议

After structural changes / 结构性修改之后

Check your edits / 检查你的修改

After each edit, read back what you changed: the text, its style, its font and any list marker. After an edit that can move the layout, such as added or removed content, a table or formatting change, or a fix to something that looked wrong, also check the rendered pages, including the pages around the change, against the list under Check the result above.

每次编辑之后回读改动:文字、样式、字体以及列表标记。编辑可能影响版式时——例如增删内容、表格或格式变更,或修复了看起来不对的地方——还要按上文"检查成果"清单核查渲染后的页面,包括改动周边的页面。

Docs and Drive tools / Docs 与 Drive 工具

Applying the design rules / 应用设计规则

Some of the design rules above act on a named style (Normal text, Heading 1 to 6) or on a page-number field, and the Docs API can apply a named style but not change one, and can't insert a page number. Others depend on the page setup. Do this instead:

上文部分设计规则作用于命名样式(Normal text、Heading 1 至 6)或页码域,而 Docs API 只能应用命名样式、不能修改样式,也无法插入页码。另一些规则依赖页面设置。请改用以下做法:

These are based on the Docs API reference and have not been tested through the connector.

以上做法依据 Docs API 参考文档整理,尚未通过连接器实测。

【评论】该节披露了连接器能力与 Docs API 能力之间的落差:样式只能套用不能定义、页码无法程序化插入,因此部分设计规则只能转达给用户手动完成;文档也如实注明这些建议未经实测。

Create / 创建

Call Drive create_file with contentMimeType: "text/html" and the document as textContent. Drive converts <h1>, <h2>, <p>, <ul>, <ol>, <b>, <i>, and <a> into native Docs formatting. This is much faster and less error-prone than building a new doc with Docs edit requests. Use the Docs connector for changes after that. For a Word file the user will download rather than edit in Google Docs, use the docx skill instead.

调用 Drive 的 create_file,使用 contentMimeType: "text/html",文档内容作为 textContent 传入。Drive 会把 <h1>、<h2>、<p>、<ul>、<ol>、<b>、<i> 和 <a> 转换为 Docs 原生格式。这比用 Docs 编辑请求从零搭建新文档快得多,也更不容易出错。此后的修改再使用 Docs 连接器。若用户要下载 Word 文件而非在 Google Docs 中编辑,改用 docx 技能。

How a doc is addressed / 文档如何寻址

Every Docs edit points at a position, so the model of positions matters more than anything else in this section.

每次 Docs 编辑都指向一个位置,因此位置模型比本节其他任何内容都重要。

【评论】Google Docs 以 UTF-16 码元为寻址单位,且每次写入都会使后续索引整体位移,这是 API 编辑错位的常见根源;本节因此要求请求按索引逆序排列、写入携带修订号守卫,并在每次写入后重新读取。

Read / 读取

There are two reads, and they serve different purposes.

读取方式有两种,用途各不相同。

Where the content lives in the read_doc JSON:

内容在 read_doc JSON 中的位置:

revisionId
tabs[].tabProperties.tabId
tabs[].documentTab.body.content[]          body elements, in order
  .paragraph.elements[].textRun.content    text, with startIndex / endIndex on the element
  .paragraph.paragraphStyle.namedStyleType HEADING_1, NORMAL_TEXT, ...
  .table.tableRows[].tableCells[].content[]  each cell holds its own paragraphs
tabs[].childTabs[]                          nested tabs, same shape

If the doc has no tabs key, the body is at the top level: body.content[].

文档没有 tabs 键时,正文位于顶层:body.content[]。

Use the helper script for positions / 用辅助脚本处理位置

scripts/docs_index.py (in this skill's folder) reads the read_doc JSON from a file and prints only what an edit needs. Where you can run code, use it rather than walking the JSON by eye. That walk is where index errors come from.

scripts/docs_index.py(位于本技能文件夹内)从文件读取 read_doc JSON,只打印编辑所需的信息。能运行代码的场合就用它,不要用肉眼遍历 JSON。索引错误正是出在肉眼遍历上。

Commands:

命令:

python <skill>/scripts/docs_index.py outline DOC.json
    one line per element: index range, style, table cell position, text.
    Pending suggestions show as [+inserted] / [-deleted].
    Ends with the body end index for appends.
python <skill>/scripts/docs_index.py find DOC.json "exact text"
    index range of every match within one paragraph, whether it is bold, and whether it sits
    in a pending suggestion. A match can't cross a non-text element, such as a chip, image or footnote mark.
python <skill>/scripts/docs_index.py fill-table DOC.json --table N --data rows.json [--bold-header]
    the full update_doc arguments (requests + writeControl) to fill empty table N, the
    TABLE #N that outline prints (every tab and nested table is counted), from a JSON list of rows.
python <skill>/scripts/docs_index.py new-table --at I --data rows.json --revision REV [--tab T] [--bold-header]
    the full update_doc arguments to insert a table at I, the endIndex - 1 of the paragraph
    it goes after, and fill it in the same call. Needs no DOC.json.

outline and find print the revisionId and the tab ID; fill-table puts the revisionId in its writeControl.

outline 和 find 会打印 revisionId 和标签页 ID;fill-table 把 revisionId 写入其 writeControl。

Edit recipes / 编辑配方

Each recipe is one update_doc call. Add tabId to every location and range when the doc has more than one tab, and add writeControl: {"requiredRevisionId": ...} to any call that uses indexes. Put real newlines in inserted text, not an escaped \n.

每个配方对应一次 update_doc 调用。文档有多个标签页时,给每个 location 和 range 加上 tabId;任何使用索引的调用都加上 writeControl: {"requiredRevisionId": ...}。插入文本中使用真实换行,而不是转义的 \n。

Change a word or phrase. replaceAllText needs no read and no indexes:

替换单词或短语。replaceAllText 无需读取、无需索引:

{"replaceAllText": {"containsText": {"text": "Q3 launch", "matchCase": true},
  "replaceText": "Q4 launch", "tabsCriteria": {"tabIds": ["t.0"]}}}

The reply reports occurrencesChanged. Zero means the text didn't match exactly: check it against read_file_content, but remember that file escapes characters like & and *. The replacement takes the style of the first character it replaces, so replacing a span that starts in bold makes the whole replacement bold. If that matters, start the find on an unstyled character, or check the result with find afterward. It changes every match in the tabs it covers (every tab unless tabsCriteria names some), so use it when every match should change, such as a date or a name the user wants changed throughout. When only one occurrence should change, or the find text is short enough to occur inside unrelated text (a bare number such as "7", a common word), delete and insert at the range find gives for that occurrence. Never put a paragraph's trailing newline in the find text: the replaced paragraph can take the next paragraph's style (a body paragraph becomes a heading), or the next paragraph can lose its heading style.

响应会报告 occurrencesChanged。为零说明文本未精确匹配:对照 read_file_content 检查,但注意该文件会转义 &、* 之类字符。替换文本继承被替换首字符的样式,因此替换以加粗开头的片段会让整个替换变粗。这有影响时,把查找起点放在无样式的字符上,或事后用 find 核查结果。它会改动其覆盖标签页中的每一处匹配(除非 tabsCriteria 另有指定,否则覆盖所有标签页),因此只应在所有匹配都应修改时使用,例如用户要求全文修改的日期或名称。当只应改一处,或查找文本短到可能出现在无关文字中(如裸数字 "7" 或常用词)时,改为在 find 给出的该处范围上先删后插。绝不要把段落的结尾换行放进查找文本:被替换段落可能继承下一段的样式(正文段落变成标题),或下一段丢失标题样式。

Rewrite a paragraph. Take its startIndex and endIndex from outline. Delete [start, end - 1], which keeps the paragraph's newline and style, then insert at start:

**重写一个段落。**从 outline 取其 startIndex 和 endIndex。删除 [start, end - 1] 以保留该段落的换行和样式,然后在 start 处插入:

[{"deleteContentRange": {"range": {"startIndex": 120, "endIndex": 184}}},
 {"insertText": {"location": {"index": 120}, "text": "New paragraph text."}}]

For several paragraphs, do the highest one first. When only some words in the paragraph change, delete and insert only those words at the range find gives, not the whole paragraph. A footnote mark, chip or image elsewhere in the paragraph then stays, and in suggestion mode the suggestion shows only the words that changed. To delete a whole paragraph, delete [start, end]. In three cases that range is refused, with "Invalid deletion range" or "The range cannot include the newline character at the end of the segment"; use these ranges instead. For the doc's last paragraph, delete from the previous paragraph's endIndex - 1 to the last paragraph's endIndex - 1. For the paragraph just before a table, and for a table cell's only paragraph, delete the text only, [start, end - 1]; an empty paragraph stays, because Google keeps one before every table and in every cell.

重写多段时先处理索引最高的一段。段落中只有部分词语变化时,只在 find 给出的范围内删除并插入那些词语,而不是整段。段落其他位置的脚注标记、chip 或图片得以保留;在建议模式下,修订也只显示变化的词语。要删除整段,就删除 [start, end]。有三种情况该范围会被拒绝,报 "Invalid deletion range" 或 "The range cannot include the newline character at the end of the segment";此时改用以下范围。对文档最后一段,从上一段的 endIndex - 1 删到最末段的 endIndex - 1。对紧邻表格之前的段落,以及表格单元格内唯一的段落,只删文字本身 [start, end - 1];空段落保留,因为 Google 会在每张表格前和每个单元格内保留一个段落。

Append to the end. Insert at the body end index minus 1 that outline prints. Start the text with a newline to begin a new paragraph. The new paragraph takes the named style of the one it splits from, so after a heading, set it to NORMAL_TEXT with updateParagraphStyle.

**追加到文末。**在 outline 打印的正文结束索引减 1 处插入。让文本以换行开头即可开启新段落。新段落继承被拆开段落的命名样式,因此在标题之后追加时,要用 updateParagraphStyle 把它设为 NORMAL_TEXT。

Insert new paragraphs with styles. Insert the text, then style ranges you compute from the insert point and the text length (in UTF-16 units). Headings use updateParagraphStyle with namedStyleType HEADING_1 to HEADING_6, TITLE, or NORMAL_TEXT and fields: "namedStyleType". Lists use createParagraphBullets over the range with a bulletPreset such as BULLET_DISC_CIRCLE_SQUARE or NUMBERED_DECIMAL_ALPHA_ROMAN. Typing "- " or "1. " makes text, not a list, and createParagraphBullets over typed markers keeps them as text, so delete them first. For nesting, put one leading tab per nesting level at the start of each nested line, before the first createParagraphBullets. It turns the tabs into levels and removes them, which shifts every later index by the number of tabs. Bulleting a paragraph directly after a list, with the same preset, adds it to that list. Inserted text takes the style of the text before it, or at the start of a paragraph the style of that paragraph's first character, so reset bold and italic on new body text with updateTextStyle (fields: "bold,italic", empty textStyle). Don't reset headings, because that removes their bold.

**插入带样式的新段落。**先插入文本,再对依据插入点和文本长度(以 UTF-16 单位计)算出的范围设置样式。标题用 updateParagraphStyle,namedStyleType 取 HEADING_1 至 HEADING_6、TITLE 或 NORMAL_TEXT,并带 fields: "namedStyleType"。列表对相应范围用 createParagraphBullets,bulletPreset 取 BULLET_DISC_CIRCLE_SQUARE 或 NUMBERED_DECIMAL_ALPHA_ROMAN 等。手动键入 "- " 或 "1. " 生成的是文本而不是列表,对已键入的标记运行 createParagraphBullets 也会把它们保留为文本,因此要先删除这些标记。需要嵌套时,在第一次 createParagraphBullets 之前,给每个嵌套行的行首按嵌套层级加相应数量的制表符。该调用把制表符转换为层级并移除它们,这会使之后的每个索引发生制表符数量的偏移。对一个紧跟在列表之后的段落用相同 preset 加项目符号,会把它并入该列表。插入的文本继承其前方文本的样式,或(在段落开头时)继承该段落首字符的样式,因此要用 updateTextStyle(fields: "bold,italic",空的 textStyle)重置新正文的加粗和斜体。不要对标题重置,那会去掉它们的加粗。

Add a table with content. One call, with no second read. Place the table after a paragraph, at that paragraph's endIndex - 1: for a table under a heading, that is the last paragraph of the section, or the heading itself if the section is empty. Never use the start of a heading: that leaves an empty heading above the table, the heading's font in its cells, and, with new-table, the heading itself turned into body text. Write the rows to a JSON file and run:

**添加带内容的表格。**一次调用完成,无需二次读取。把表格放在某个段落之后、该段落 endIndex - 1 的位置:标题下的表格,该位置就是本节最后一个段落;节为空时就是标题本身。绝不要用标题的起始位置:那会在表格上方留下一个空标题,让表格单元格带上标题字体,而且用 new-table 时标题本身会变成正文。把行数据写入 JSON 文件,然后运行:

python <skill>/scripts/docs_index.py new-table --at <endIndex - 1> --data rows.json --revision <revisionId> [--tab <tabId>] [--bold-header]

Pass its output as the requests and writeControl of one update_doc call. It inserts the table, fills the cells, bolds the header row with --bold-header, and sets the empty paragraph Google adds after the table to NORMAL_TEXT (otherwise, after a heading, it becomes an empty heading). Pass --tab whenever the doc has more than one tab; without it every request goes to the first tab. The command needs only the index, the revisionId and the tabId, which you can read from read_doc even when the result came back in the chat rather than as a file.

把它的输出作为一次 update_doc 调用的 requests 和 writeControl。它会插入表格、填充单元格、按 --bold-header 加粗表头行,并把 Google 在表格后自动添加的空段落设为 NORMAL_TEXT(否则,在标题之后它会变成一个空标题)。文档有多个标签页时必须传 --tab;不传则所有请求都落到第一个标签页。该命令只需要索引、revisionId 和 tabId;即使 read_doc 结果是返回在对话里而非保存为文件,你也能读到这三项。

Without the script, put the same requests in one batch: insertTable at index i makes a table that starts at i + 1; in an R x C table, cell (r, c)'s text goes at i + 4 + r × (2C + 1) + 2c, and the empty paragraph after the table is at i + 3 + R × (2C + 1) until you insert text, so put its NORMAL_TEXT reset right after insertTable. Fill from the last cell to the first, so each insert only shifts cells already filled.

不用脚本时,把同样的请求放进一个批次:在索引 i 处 insertTable 生成的表格从 i + 1 开始;R 行 C 列的表格中,单元格 (r, c) 的文字位于 i + 4 + r × (2C + 1) + 2c,表格后的空段落在你插入文字之前位于 i + 3 + R × (2C + 1),因此把它的 NORMAL_TEXT 重置紧跟在 insertTable 之后。从最后一个单元格向前逐个填充,这样每次插入只会移动已填充过的单元格。

To fill a table that already exists, a cell's text goes at its first paragraph's startIndex, which is the cell's own startIndex + 1; Google rejects an insert at the cell's startIndex ("The insertion index must be inside the bounds of an existing paragraph"). With a saved read, fill-table builds these requests; it assumes the cells are empty.

填充既有表格时,单元格文字位于其首个段落的 startIndex,即该单元格自身 startIndex + 1 的位置;在单元格的 startIndex 处插入会被 Google 拒绝("The insertion index must be inside the bounds of an existing paragraph")。有已保存的读取结果时,fill-table 会构建这些请求;它假定单元格为空。

Change table structure. insertTableRow, deleteTableRow, insertTableColumn, and deleteTableColumn take tableCellLocation: {"tableStartLocation": {"index": <table startIndex>}, "rowIndex": r, "columnIndex": c}. updateTableCellStyle sets cell backgrounds over a tableRange built from the same location plus rowSpan and columnSpan. Colors use rgbColor values from 0 to 1. A row inserted below a bold header row comes out bold, and a new column copies its neighbor's width and background. To delete a whole table, delete exactly [table startIndex, table endIndex].

修改表格结构。insertTableRow、deleteTableRow、insertTableColumn 和 deleteTableColumn 接受 tableCellLocation: {"tableStartLocation": {"index": <table startIndex>}, "rowIndex": r, "columnIndex": c}。updateTableCellStyle 通过由同一位置加上 rowSpan 和 columnSpan 构成的 tableRange 设置单元格背景。颜色使用 0 到 1 的 rgbColor 值。在加粗表头行下方插入的行会带加粗,新列会复制相邻列的宽度和背景色。要删除整张表格,精确删除 [table startIndex, table endIndex]。

Suggest instead of edit. Add "writeMode": "SUGGEST" to writeControl, and the same requests land as tracked suggestions that the doc's owner can accept or reject. Use it when the user asks for suggestions, redlines, tracked changes, or a review, or when the doc belongs to someone else and the user wants to propose rather than change. You can't accept or reject suggestions through the API, so tell the user they're waiting in the doc. Before you tell them, read the doc again with read_doc and run outline: inserted and deleted text should show as [+...] or [-...] (outline doesn't show suggested formatting changes). If new text shows as plain text, or deleted text is gone instead of showing as [-...], the change was made directly; say so, and don't call it a suggestion. Suggested deletions stay in the index space until someone resolves them; see "How a doc is addressed". The connector has answered this mode with "Unsupported WriteControl mode". If it does, make no direct edits in its place: tell the user suggestions aren't available, and offer to list the proposed changes in your reply or to edit directly.

**以建议模式代替直接编辑。**在 writeControl 中加上 "writeMode": "SUGGEST",同样的请求会以跟踪修订的形式落地,由文档所有者接受或拒绝。用户要求建议、红线批注、修订跟踪或审阅时,或文档属于他人而用户想提案而非直接修改时使用。API 无法接受或拒绝建议,因此要告知用户建议正在文档中等候处理。告知之前,先用 read_doc 重读文档并运行 outline:插入和删除的文本应显示为 [+...] 或 [-...](outline 不显示建议的格式变更)。若新文本显示为普通文本,或被删文本直接消失而没有显示为 [-...],说明改动是直接做出的;要如实说明,不要称之为建议。建议的删除在有人处理之前一直占据索引空间,见"文档如何寻址"一节。连接器曾对该模式返回 "Unsupported WriteControl mode"。若遇到,不要改用直接编辑:告知用户建议功能不可用,并提出可以在回复中列出拟议改动,或直接编辑。

{"documentId": "...", "requests": [...],
 "writeControl": {"writeMode": "SUGGEST", "requiredRevisionId": "..."}}

Tabs. addDocumentTab with tabProperties.title creates a tab, and the reply holds its tabId. updateDocumentTabProperties renames one (fields: "title"), and deleteTab removes one along with its child tabs, but not the only tab. Set tabProperties.parentTabId to create a child tab; tabs nest at most three levels deep. A new tab starts with one empty paragraph, so its first insert index is 1.

标签页。addDocumentTab 带 tabProperties.title 创建标签页,响应中含其 tabId。updateDocumentTabProperties 重命名标签页(fields: "title");deleteTab 删除标签页及其子标签页,但唯一标签页不可删。设置 tabProperties.parentTabId 可创建子标签页;标签页最多嵌套三层。新标签页以一个空段落开始,因此其首个插入索引为 1。

Verify / 验证

Docs failures / Docs 常见故障

Symptom Cause Fix
read_doc result too large or cut off Full document JSON for a long or table-heavy doc Orient with Drive read_file_content. Use replaceAllText where the find text matches only the text you mean to change (add neighboring words until it does). If the result was saved to a file, run docs_index.py on it.
An edit landed in the wrong tab No tabId in the location or range Add the tabId from the read or from the URL's ?tab= value.
replaceAllText changed other tabs No tabsCriteria Scope it with tabsCriteria.tabIds.
replaceAllText reports 0 occurrences Find text copied from read_file_content, which escapes &, *, and similar characters, or glues suggestions Use the literal text, or check it with docs_index.py find.
Text shows as "RBRunning back" A pending suggestion read as plain text Read with read_doc. outline marks suggested text as [+...] and [-...].
A heading loses its bold after an edit A style reset was applied to the heading Reset styles only on body text.
Replaced text turned bold The replacement inherited the style of the first replaced character Clear it with updateTextStyle over the new range.
Edits land in the wrong place Requests ran from the lowest index to the highest, or used indexes from before an earlier write Order requests from the highest index to the lowest, and read again after every write.
Typed "- " shows as text, not a bullet Lists are paragraph properties Delete the typed markers, then use createParagraphBullets over the range. Bulleting keeps typed markers as text.
症状 原因 解决方法
read_doc 结果过大或被截断 长文档或表格繁多的文档的完整 JSON 先用 Drive 的 read_file_content 了解全貌。在查找文本只匹配目标文字处使用 replaceAllText(不断加入相邻词语直到唯一匹配)。结果已保存为文件时,对其运行 docs_index.py。
编辑落到了错误的标签页 location 或 range 缺少 tabId 加上读取结果或 URL ?tab= 参数中的 tabId。
replaceAllText 改动了其他标签页 缺少 tabsCriteria 用 tabsCriteria.tabIds 限定范围。
replaceAllText 报告 0 处匹配 查找文本复制自 read_file_content,其中 &、* 等字符已被转义,或建议内容与正文粘连 使用字面文本,或用 docs_index.py find 核查。
文本显示为 "RBRunning back" 待处理的建议被当作普通文本读取 用 read_doc 读取。outline 会把建议文本标为 [+...] 和 [-...]。
标题在编辑后失去加粗 对标题执行了样式重置 只对正文文本重置样式。
被替换文本变成加粗 替换继承了被替换首字符的样式 对新范围用 updateTextStyle 清除。
编辑落在错误位置 请求按索引从低到高执行,或使用了早前写入之前读取的索引 请求按索引从高到低排序,且每次写入后重新读取。
手动键入的 "- " 显示为文本而非项目符号 列表是段落属性 删除键入的标记,再对该范围运行 createParagraphBullets。加项目符号会把键入的标记保留为文本。