feat(docs): extend find-replace with markdown, images, and first-occurrence support#305
feat(docs): extend find-replace with markdown, images, and first-occurrence support#305chrismdp wants to merge 5 commits intoopenclaw:mainfrom
Conversation
|
Hey! Noticed the great Just wanted to flag why this PR is still relevant. The two commands solve different problems:
The main use case is template-style workflows — find a placeholder like |
87c0820 to
9f65638
Compare
|
@steipete — updated approach: instead of adding a separate
The default behaviour ( The image pipeline reuses the shared functions from Single squashed commit, 13 tests, manually tested all paths against a live doc. |
9f65638 to
97bd9d2
Compare
…rrence support Adds --format=markdown, --first, and --content-file flags to the existing `docs find-replace` command, giving it the capabilities that were previously prototyped in a separate `docs replace` command. Four operational paths: - Plain replace-all (default): ReplaceAllText API — unchanged behaviour - Plain --first: find first occurrence, delete + insert (revision-pinned) - Markdown --first: find first, delete + insert with formatting + image pipeline - Markdown replace-all: loop over occurrences, applying markdown each iteration The shared image pipeline (extractMarkdownImages, insertImagesIntoDocs) from docs_import.go is reused for inline image support (). Inline images are now capped to 468pt width (US Letter content width) by default, maintaining aspect ratio. Previously images inserted at native resolution which could be far larger than the page. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
97bd9d2 to
d963196
Compare
Add {width=N height=N} / {w=N h=N} syntax to the markdown image pipeline,
allowing control over inserted image size instead of always using 468pt.
Extract shared parseImageDimAttrs helper, reused by both the import and
sed image pipelines to eliminate duplicated attribute parsing logic.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add {width=N height=N} sizing syntax to --format and --file help
strings so the feature is discoverable from the CLI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ssaging findPlaceholderIndices searched within individual TextRun elements, so placeholders split across runs by Drive's markdown converter were never found — causing silent image insertion failures. Fix by concatenating all text runs within each paragraph before searching, then mapping byte offsets back to absolute UTF-16 document indices. Also improve the error message when local images resolve outside the markdown file directory — now explains the constraint and suggests using relative paths. Updated help text for --file and --format to document the local image path requirement. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Drive's markdown converter places table cell content inside Table > TableRow > TableCell > Paragraph structures. The placeholder search only walked top-level Body.Content paragraphs, so images inside markdown tables were never found — causing silent insertion failures. Fix by extracting searchElements/searchParagraph helpers that recurse into table structures. Confirmed with manual test against a real markdown file with images in table cells. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…rrence support (#305) Co-authored-by: Chris Parsons <chris.p@rsons.org> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
Landed on Extra land fixes included:
Verification: |
…rrence support (openclaw#305) Co-authored-by: Chris Parsons <chris.p@rsons.org> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Extends the existing
docs find-replacecommand with three new flags, folding in the capabilities that were previously prototyped as a separatedocs replacecommand:--format=markdown— replacement text is parsed as markdown and applied with native Google Docs formatting (bold, italic, headings, lists, code blocks, tables, inline images via)--first— replace only the first occurrence instead of all (uses revision-pinned delete + insert rather thanReplaceAllTextAPI)--content-file=PATH— read replacement text from a file instead of the positional argumentBackwards compatibility
gog docs find-replace <docId> <find> <replace> [--match-case]works identically to before — plain-text replace-all via theReplaceAllTextAPI. No flags changed meaning;replacepositional arg is now optional (omit when using--content-file).Four operational paths
--format--firstplain(default)ReplaceAllTextAPI — unchanged from mainplainmarkdownmarkdownImage pipeline
Reuses the shared two-pass image pipeline from
docs_import.go:extractMarkdownImagesstrips→<<IMG_token_N>>placeholdersinsertImagesIntoDocsreads doc back, finds placeholders, replaces withInsertInlineImagecleanupImagePlaceholdersremoves any leftover placeholders (belt-and-suspenders)Custom image dimensions
Supports Pandoc-style
{width=N height=N}attributes on markdown images:The attribute parsing is shared between the import and sed image pipelines via
parseImageDimAttrs.Files changed
internal/cmd/docs.goDocsFindReplaceCmdstruct +Run(), addedrunReplaceAll/runPlain/runMarkdown/resolveReplaceText/insertImages/printFirstResultmethods, removedDocsReplaceCmdentirelyinternal/cmd/docs_find_replace_test.gointernal/cmd/docs_import.gowidthPt/heightPtfields, extended regex for{…}attributes, sharedparseImageDimAttrshelper, dimension-awarebuildImageInsertRequestsinternal/cmd/docs_import_test.gointernal/cmd/docs_import_security_test.gointernal/cmd/docs_sed_images.goparseImageSyntaxto use sharedparseImageDimAttrsTest plan
go build ./...go test ./internal/cmd/... -run "TestDocsFindReplace|TestFindTextInDoc"— 13/13 passgo test ./internal/cmd/... -run "TestExtractMarkdownImages|TestBuildImageInsert"— all passgo test ./internal/cmd/... -run "TestParseImageSyntax"— all pass (sed refactoring)go vet ./internal/cmd/...— cleango test ./internal/cmd/...— pass🤖 Generated with Claude Code