Skip to content

Support reading tables in Google Docs - #518

Open
ndisidore wants to merge 3 commits into
mainfrom
fix/google-doc-table-support
Open

ndisidore wants to merge 3 commits into
mainfrom
fix/google-doc-table-support

Conversation

@ndisidore

@ndisidore ndisidore commented Sep 16, 2026

Copy link
Copy Markdown
Member

Previously in Google Docs docTabToMarkdown() previously processed only paragraph structural elements. This updates it to include tables as well

Google documentation

The Google Docs API explicitly exposes table cells through documents.get():

  • Document structure overview: explains that documents.get() returns the complete document as structured JSON.
  • StructuralElement: body elements can be paragraphs, section breaks, tables, or tables of contents.
  • Table: contains tableRows[].
  • TableRow: contains tableCells[].
  • TableCell: contains recursive content[] structural elements, including the cell’s paragraphs and nested tables.
  • documents.get: retrieves that document structure.

i.e.

Document
└─ Tab.documentTab.body.content[]
   └─ StructuralElement.table
      └─ tableRows[]
         └─ tableCells[]
            └─ content[]
               └─ StructuralElement.paragraph
                  └─ elements[].textRun.content

Devin Review

@github-actions github-actions Bot added the gatekeeper Changes to a gatekeeper integration label Sep 16, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

@github-actions

Copy link
Copy Markdown

Preview: pr518-fix-google-do-2cddb46f

https://pr518-fix-google-do-2cddb46f-router.cloudflare-os-previews.workers.dev

Dashboard · deleted when this PR closes

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 16, 2026

Copy link
Copy Markdown

Submitted 1 actionable inline finding.

github run

devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 16, 2026

Copy link
Copy Markdown

Submitted 1 actionable inline finding.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from 06465ca to dd52b13 Compare September 16, 2026 22:56
devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 16, 2026

Copy link
Copy Markdown

Submitted 2 actionable inline findings.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from dd52b13 to c56ddca Compare September 16, 2026 23:22
ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 16, 2026

Copy link
Copy Markdown

Submitted 2 actionable inline findings.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from c56ddca to 7418c94 Compare September 16, 2026 23:56
devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 17, 2026

Copy link
Copy Markdown

Submitted 2 actionable inline findings.

github run

devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 17, 2026

Copy link
Copy Markdown

Submitted 3 actionable inline findings.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from a3644c8 to 3b5cd7c Compare September 17, 2026 15:27
devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 17, 2026

Copy link
Copy Markdown

Submitted 1 actionable inline finding.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from 3b5cd7c to cc29952 Compare September 17, 2026 15:53
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 19, 2026

Copy link
Copy Markdown

Submitted 1 actionable inline finding.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from bdd0303 to cc16b87 Compare September 20, 2026 14:40
devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 20, 2026

Copy link
Copy Markdown

Submitted 2 actionable inline findings.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from cc16b87 to c2f4176 Compare September 21, 2026 14:07
devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 21, 2026

Copy link
Copy Markdown

Submitted 2 actionable inline findings.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from c2f4176 to be09ef1 Compare September 21, 2026 16:53
devin-ai-integration[bot]

This comment was marked as resolved.

@ask-bonk

This comment was marked as outdated.

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from be09ef1 to f4f838e Compare September 21, 2026 19:07
@ask-bonk

ask-bonk Bot commented Sep 21, 2026

Copy link
Copy Markdown
  • Medium packages/gatekeeper-google/src/markdown-converter.ts:1475: Replacing an interrupted list item 2. Second with 3. Second previews 3, but bullet recreation discards the requested ordinal and Google commits 1. Second. Normalize unsupported restarts or reject them before approval.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from f4f838e to f0c7d6c Compare September 21, 2026 19:48
let level = lists[bullet.listId]?.listProperties.nestingLevels[nestingLevel];
return {
listId: bullet.listId,
listType: level?.glyphType !== undefined ? "numbered" : "bullet",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium: The documented glyphType: "NONE" renders an empty glyph, but this classifies every present glyph type as a numbered list. A valid cell whose paragraph has bullet: { listId: "L" } and whose lists.L.listProperties.nestingLevels[0] is { glyphType: "NONE", glyphFormat: "%0" } is displayed by Docs with no marker; this renderer emits <ol><li>Text</li></ol>, inventing 1. (and the body path likewise invents 1. ). Handle NONE as a markerless level rather than ordered.

): boolean {
return startsMarkdownEscape(markdown, index - 1) ||
links.some(link => index > link.mdStart && index < link.mdEnd) ||
index > 0 && index < markdown.length && markdown[index - 1] === markdown[index] &&

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium: This boundary check protects only positions inside a delimiter run, not inside the inline style span that the delimiters form. For a provider paragraph containing plain malformed-but-supported text *x, replaceText("*x", "*x*") previews a complete italic span, and parsing the whole replacement would insert x with italic: true. Here the shared *x is retained, however, so materialization passes only the final * to markdownToDocRequests; the generated batch merely inserts that literal character with an empty text style, leaving all three characters plain. The same occurs when completing ~~x to ~~x~~. Expand trim bounds to the complete resulting inline formatting span (as is already done for links), and cover completion of an unmatched delimiter.

@ask-bonk

ask-bonk Bot commented Sep 21, 2026

Copy link
Copy Markdown
  • Medium markdown-converter.ts:1579: Changing a bullet item to numbered treats both as the same list boundary. Simulation omits the blank separator that appears after materialization, invalidating dependent edits.
  • Medium markdown-converter.ts:548: Valid glyphType: "NONE" lists render as <ol>, inventing numbering for markerless table-cell lists.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from f0c7d6c to 168740c Compare September 21, 2026 21:23
devin-ai-integration[bot]

This comment was marked as resolved.

ask-bonk[bot]

This comment was marked as resolved.

@ask-bonk

ask-bonk Bot commented Sep 21, 2026

Copy link
Copy Markdown

Submitted 1 actionable inline finding.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from 168740c to c53d095 Compare September 21, 2026 22:12
@ask-bonk

ask-bonk Bot commented Sep 21, 2026

Copy link
Copy Markdown
  • Medium markdown-converter.ts:957: Token-boundary trimming is quadratic. A 280 KB formatted replacement took ~3.8s; larger valid Docs can exhaust Worker CPU. Index ranges instead of rescanning all ranges per character.
  • Medium markdown-converter.ts:1511: Style ranges include characters Google strips from insertText. Inputs containing controls/private-use characters can style neighboring text or invalidate the batch. Sanitize before calculating offsets.
  • Medium markdown-converter.ts:462: Table cells emit Google’s U+000B manual line breaks as raw control characters, so HTML consumers lose the visible break. Render them as <br>.

github run

@ndisidore
ndisidore force-pushed the fix/google-doc-table-support branch from c53d095 to 8b79dd6 Compare September 21, 2026 23:13
bounds = markdownReplacementBounds(oldMarkdown, newMarkdown);
}
let { prefixLen, suffixLen } = bounds;
let changed = newMarkdown.slice(prefixLen, newMarkdown.length - suffixLen);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Medium: Canonicalizing only the trimmed fragment misses a newly created plain-paragraph boundary. For an existing A\n\nB, replaceText("A\n\nB", "A\nX\nB") trims the change to just X, so simulation remains A\nX\nB. Materialization recognizes the insertion point as following a paragraph and inserts \nX, creating three provider paragraphs; the next read renders them as A\n\nX\n\nB. Any dependent queued edit against the approved preview is then invalidated. Please canonicalize/rebuild with the adjacent block boundaries and add an action-level replay case.

@ask-bonk

ask-bonk Bot commented Sep 21, 2026

Copy link
Copy Markdown

Submitted 1 actionable inline finding.

github run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gatekeeper Changes to a gatekeeper integration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant