Google Docs authoring
Locate text, never compute indexes (the #1 source of bugs)
Docs edits address zero-based UTF-16 index ranges within one tab, and every
write SHIFTS later indexes. Guessed or stale indexes silently hit the wrong
paragraphs - the classic symptom is two lists merging into one continued
numbering. The tools remove the need for index math:
- returns FRESH ranges for exact text - the
direct source of indexes for , ,
, and . Locate, then edit, in
back-to-back calls.
- takes / anchors and resolves
the range itself: name the first and last item paragraphs and no index
ever touches your hands. Use one per list with the right
preset (BULLET_* for bullets, NUMBERED_* for numbers); never stretch one
call across two visually separate lists.
When a range must come from structure instead of a phrase (styling a whole
paragraph, addressing a table), read it from
elements: a
paragraph's
is the range for paragraph-level tools. END IS
EXCLUSIVE: one short misses the last character, one long styles the
character after the phrase (the classic italic-or-link off-by-one).
When raw indexes are unavoidable:
first, compute ONE edit,
pass
, apply, and re-read before the next positional
edit. Order multi-part positional work BACK-TO-FRONT (highest index first)
when re-reading between steps is too expensive; earlier ranges stay valid.
Creating a document
makes a BLANK doc (its API ignores content), so plan:
- Content known up front: prefer google-drive
with Markdown (
target_mime_type: ...document
), which imports headings,
lists, and tables in one call and can target a folder.
- Building incrementally: , then with
omitted to APPEND each paragraph; append mode reads the tail itself and is
revision-guarded automatically. styles the new paragraphs
and / style the inserted text in the same call, so a
well-structured document is a sequence of appends with no styling pass.
- Doc creates cannot set a parent folder. When placement matters, create
and then google-drive
google_drive_move_or_rename
with
.
Structure is not optional
A document without hierarchy reads as a text dump. Default shape for any
report/memo/notes request: a TITLE paragraph, an italic byline or date line,
HEADING_2 per section, short body paragraphs with bold on the phrases that
matter, and bulleted lists for enumerations. Use
's
paragraphStyle/bold/italic arguments as you write rather than styling
afterwards.
Styling
- Character styling (): bold/italic/underline/strike,
fontSize, fontFamily, textColor/backgroundColor as , linkUrl.
Exclusive END index: to style one paragraph without its trailing newline,
use from the read.
- Paragraph styling: for named styles
(TITLE/HEADING_1..6), for alignment, indents, and
line spacing (percent, 100 = single).
- Lists: over the paragraphs' range; each newline-separated
paragraph becomes one item. Insert the plain lines first, then bullet them.
- The preset is part of correctness: enumerations get a BULLET_* preset by
default; NUMBERED_* only when the content is ordered (steps, rankings) or
the request says numbered.
- Before bulleting, check the read for paragraphs that ALREADY show a
leading bullet - text appended directly after a list inherits its
membership, and over such paragraphs restyles the ORIGINAL
list, continuing its numbering (a second list showing 4, 5, 6). Strip
first: with over exactly the new paragraphs,
then apply the wanted preset.
Tables and images
- inserts an EMPTY grid. To fill it: re-read (cells appear
with their own index ranges) and into cells from the LAST
cell to the first, so earlier cell indexes stay valid.
- Style a table AFTER filling it, addressing it by the table element's
from : the header row
(pick the row's text color against that fill), for a
title cell spanning columns (top-left content survives, the rest is
dropped), for fixed widths in points. Structural
edits (merge) shift indexes: re-read before further text edits.
- needs a PUBLICLY fetchable URL (Google fetches it; auth
walls and private hosts fail), PNG/JPEG/GIF. Size with width/height in
points (aspect kept when only one is set).
- starts a new page at an index.
Headers and footers
sets the default header or footer in one call: it
creates the segment when the doc has none, replaces the text otherwise,
and empty text clears it. The text is static (no page-number fields exist
in the API); it applies to the first tab. Never
a fake header
into the body - it scrolls away with the content.
Bulk text ops
replaces literal strings everywhere (or in named tabs) with
no index math; prefer it for renames and corrections.
rejects ranges that split table structure or surrogate pairs; deleting a
paragraph's final newline merges it with the next.
Verify your work
Re-read with
for structure and styles, or google-drive
for the whole doc as Markdown, or
(pdf) when the visual result matters. After any
styling call, confirm the styled span covers exactly the intended text
before moving on.