-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Google Docs - new components #18153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Google Docs - new components #18153
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
WalkthroughIntroduces new Google Docs actions for getting tab content and inserting text, tables, and page breaks; adds tabId propDefinition and helper methods to the Google Docs app; updates replace-text to support tab-scoped replacements; and bumps versions across several actions, sources, and package metadata. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant Action as Insert Text Action
participant App as Google Docs App
participant Google as Google Docs API
User->>Action: Provide docId, text, index, [tabId]
Action->>App: _batchUpdate(docId, "insertText", { text, location:{ index, tabId } })
App->>Google: documents.batchUpdate
Google-->>App: update result
Action->>App: getDocument(docId, !!tabId)
App->>Google: documents.get(?includeTabsContent=true if tabId)
Google-->>App: document
App-->>Action: document
Action-->>User: document (+$summary)
sequenceDiagram
actor User
participant Action as Replace Text Action
participant App as Google Docs App
participant Google as Google Docs API
User->>Action: docId, replaceText, containsText, [tabIds]
Action->>App: _batchUpdate(docId, "replaceAllText", { replaceText, containsText, tabsCriteria? })
App->>Google: documents.batchUpdate
Google-->>App: result
Action-->>User: $summary
sequenceDiagram
actor User
participant Action as Insert Table / Page Break
participant App as Google Docs App
participant Google as Google Docs API
User->>Action: docId, rows/cols or index, [tabId]
Action->>App: insertTable/insertPageBreak(docId, request)
App->>Google: documents.batchUpdate
Google-->>App: result
Action->>App: getDocument(docId, !!tabId)
App->>Google: documents.get
Google-->>App: document
App-->>Action: document
Action-->>User: document (+$summary)
sequenceDiagram
actor User
participant Action as Get Tab Content
participant App as Google Docs App
participant Google as Google Docs API
User->>Action: docId, [tabIds]
Action->>App: getDocument(docId, true)
App->>Google: documents.get?includeTabsContent=true
Google-->>App: document with tabs
App-->>Action: document
Action->>Action: filter tabs by tabIds
Action-->>User: filtered tabs (+$summary)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related PRs
Suggested reviewers
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
components/google_docs/actions/append-text/append-text.mjs (1)
31-37
: Await the getDocument call to avoid returning a Promise in action output.
getDocument
is async and should be awaited; otherwise the action returns a Promise instead of the document object and can break downstream steps expecting a JSON object.Apply this diff:
async run({ $ }) { await this.googleDocs.insertText(this.docId, { text: this.text, }, this.appendAtBeginning); - const doc = this.googleDocs.getDocument(this.docId); + const doc = await this.googleDocs.getDocument(this.docId); $.export("$summary", `Successfully appended text to document with ID: ${this.docId}`); return doc; },components/google_docs/actions/replace-image/replace-image.mjs (1)
35-43
: Await the getDocument call to return the resolved document.Same pattern as other actions:
getDocument
should be awaited to avoid leaking a Promise from the action.await this.googleDocs.replaceImage(this.docId, image); - const doc = this.googleDocs.getDocument(this.docId); + const doc = await this.googleDocs.getDocument(this.docId); $.export("$summary", `Successfully replaced image in doc with ID: ${this.docId}`); return doc;
🧹 Nitpick comments (18)
components/google_docs/actions/replace-image/replace-image.mjs (1)
6-6
: Minor grammar improvement in description.- description: "Replace image in a existing document. [See the documentation](https://developers.google.com/docs/api/reference/rest/v1/documents/request#ReplaceImageRequest)", + description: "Replace an image in an existing document. [See the documentation](https://developers.google.com/docs/api/reference/rest/v1/documents/request#ReplaceImageRequest)",components/google_docs/actions/get-document/get-document.mjs (2)
30-37
: Defensive option mapping for tabs without properties.If any tab lacks
tabProperties
(edge cases, API changes), the current map would throw. Consider a safe fallback.- return tabs.map((tab) => ({ - label: tab.tabProperties.title, - value: tab.tabProperties.tabId, - })); + return tabs + .filter((tab) => tab?.tabProperties?.tabId) + .map((tab) => ({ + label: tab.tabProperties.title ?? tab.tabProperties.tabId, + value: tab.tabProperties.tabId, + }));
41-49
: Guard against undefinedresponse.tabs
when filtering selected tabIds.If the API returns no
tabs
array (or the call didn’t include tabs content), filtering will throw. You already enforceincludeTabsContent
whentabIds
are passed; this small guard avoids runtime errors if the API response differs.- if (this.tabIds?.length) { - response.tabs = response.tabs.filter((tab) => this.tabIds.includes(tab.tabProperties.tabId)); - } + if (this.tabIds?.length) { + const tabs = Array.isArray(response.tabs) ? response.tabs : []; + response.tabs = tabs.filter((tab) => this.tabIds.includes(tab?.tabProperties?.tabId)); + }components/google_docs/google_docs.app.mjs (1)
150-161
: New API wrappers align with Docs API request names.
insertTable
,insertPageBreak
, andcreateDocument
correctly delegate to_batchUpdate
/documents.create
. The thin wrappers match expected request shapes when callers pass properly structured bodies (withlocation
, etc.). No issues spotted.If you anticipate more wrappers, consider centralizing request-name constants to avoid typos and enable reuse (e.g.,
const REQ = { INSERT_TABLE: "insertTable", ... }
).components/google_docs/actions/replace-text/replace-text.mjs (2)
59-63
: Avoid sending an empty tabsCriteria; gate on lengthIf the UI binds tabIds to an empty array, the current truthy check will still send tabsCriteria: { tabIds: [] }, which is semantically different from omitting the field (and could be rejected by the API). Check for length instead.
- tabsCriteria: this.tabIds - ? { - tabIds: this.tabIds, - } - : undefined, + tabsCriteria: this.tabIds?.length + ? { tabIds: this.tabIds } + : undefined,Docs: tabsCriteria is optional; omitting it applies to all tabs. (developers.google.com)
65-69
: Return the resolved document and include tabs when targeting tabsFor consistency with other actions and to avoid returning a pending Promise, await getDocument. Also pass includeTabsContent when specific tabs were targeted, so the response mirrors the edit context.
- const doc = this.googleDocs.getDocument(this.docId); - $.export("$summary", `Successfully replaced text in doc with ID: ${this.docId}`); - return doc; + const doc = await this.googleDocs.getDocument(this.docId, Boolean(this.tabIds?.length)); + $.export("$summary", `Successfully replaced text in doc with ID: ${this.docId}`); + return doc;components/google_docs/actions/insert-page-break/insert-page-break.mjs (3)
17-23
: Clarify index is zero-based UTF-16 code unitsGoogle Docs Location.index is zero-based (UTF-16 code units). Clarifying this in the UI label/description avoids confusion.
- index: { - type: "integer", - label: "Index", - description: "The index to insert the page break at", + index: { + type: "integer", + label: "Index (0-based)", + description: "Zero-based index (UTF-16 code units) to insert the page break at", default: 1, optional: true, },Reference for zero-based index and location semantics. (developers.google.com)
24-33
: Make tabId explicitly optional to work on non-tabbed docsUnless the app propDefinition already marks tabId as optional, add optional: true here to avoid forcing a selection on single-tab or no-tab docs.
tabId: { propDefinition: [ googleDocs, "tabId", (c) => ({ documentId: c.docId, }), ], + optional: true, },
34-45
: Await the returned document and include doc ID in summary
- Await getDocument so the action returns a resolved resource.
- Including the doc ID in the summary improves UX consistency with other actions.
- await this.googleDocs.insertPageBreak(this.docId, pageBreak); - $.export("$summary", "Successfully inserted page break"); - return this.googleDocs.getDocument(this.docId, !!this.tabId); + await this.googleDocs.insertPageBreak(this.docId, pageBreak); + $.export("$summary", `Successfully inserted page break in doc with ID: ${this.docId}`); + return await this.googleDocs.getDocument(this.docId, !!this.tabId);Docs confirm Location supports tabId and zero-based index. (developers.google.com)
components/google_docs/actions/insert-text/insert-text.mjs (3)
23-29
: Clarify index is zero-based UTF-16 code unitsSame context as page break: Location.index is zero-based. Clarify in the UI.
- index: { - type: "integer", - label: "Index", - description: "The index to insert the text at", + index: { + type: "integer", + label: "Index (0-based)", + description: "Zero-based index (UTF-16 code units) at which to insert the text", default: 1, optional: true, },Reference for Location index semantics. (developers.google.com)
30-38
: Make tabId explicitly optional to support single/no-tab docsAligns with other actions and avoids requiring a selection when unnecessary.
tabId: { propDefinition: [ googleDocs, "tabId", (c) => ({ documentId: c.docId, }), ], + optional: true, },
40-52
: Await getDocument and include the doc ID in the summaryReturn a resolved document and make the summary more informative. This also mirrors the Replace Text action’s summary style.
- await this.googleDocs._batchUpdate(this.docId, "insertText", text); - $.export("$summary", "Successfully inserted text"); - return this.googleDocs.getDocument(this.docId, !!this.tabId); + await this.googleDocs._batchUpdate(this.docId, "insertText", text); + $.export("$summary", `Successfully inserted text in doc with ID: ${this.docId}`); + return await this.googleDocs.getDocument(this.docId, !!this.tabId);Docs confirm InsertTextRequest.location supports tabId. (developers.google.com)
components/google_docs/actions/get-tab-content/get-tab-content.mjs (1)
17-29
: Make tabIds optional and usable as a filter (not a requirement)If the user doesn’t select any tabs, returning all tabs is a sensible default. Mark the prop optional to match that behavior.
tabIds: { type: "string[]", label: "Tab IDs", description: "Return content for the specified tabs", + optional: true, async options() { const { tabs } = await this.googleDocs.getDocument(this.docId, true); if (!tabs?.length) return []; return tabs.map((tab) => ({ label: tab.tabProperties.title, value: tab.tabProperties.tabId, })); }, },
components/google_docs/actions/insert-table/insert-table.mjs (5)
4-9
: Action metadata is clear and consistent.Key, name, version, and description follow existing conventions. Minor nit: consider clarifying in the description that the index is 1-based to set expectations for users.
- description: "Insert a table into a document. [See the documentation](https://developers.google.com/workspace/docs/api/reference/rest/v1/documents/request#inserttablerequest)", + description: "Insert a table into a document (index is 1-based). [See the documentation](https://developers.google.com/workspace/docs/api/reference/rest/v1/documents/request#inserttablerequest)",
17-26
: Add client-side validation hints for rows/columns.Preventing zero/negative values at the UI layer reduces avoidable API 400s and improves UX.
rows: { type: "integer", label: "Rows", description: "The number of rows in the table", + min: 1, }, columns: { type: "integer", label: "Columns", description: "The number of columns in the table", + min: 1, },
27-33
: Clarify 1-based index and enforce a lower bound.Docs treat indices as 1-based. Add min and mention 1-based to avoid confusion, off-by-one mistakes, and bad requests.
index: { type: "integer", label: "Index", - description: "The index to insert the table at", + description: "The 1-based index to insert the table at", default: 1, optional: true, + min: 1, },Optional: consider an “Append to end” boolean that switches to an end-of-segment insertion path if supported by your app wrapper.
45-52
: Guard inputs and avoid sending undefined tabId.Add minimal runtime validation and only include tabId when provided. This avoids relying on JSON serialization to strip
undefined
and produces clearer requests.- const table = { - rows: this.rows, - columns: this.columns, - location: { - index: this.index, - tabId: this.tabId, - }, - }; + if (!Number.isInteger(this.rows) || this.rows < 1) { + throw new Error("Rows must be a positive integer"); + } + if (!Number.isInteger(this.columns) || this.columns < 1) { + throw new Error("Columns must be a positive integer"); + } + if (!Number.isInteger(this.index) || this.index < 1) { + throw new Error("Index must be a positive integer (1-based)"); + } + const location = { index: this.index }; + if (this.tabId) location.tabId = this.tabId; + const table = { + rows: this.rows, + columns: this.columns, + location, + };
53-56
: insert-table action: methods verified and optional enhancements suggested
- Verified that
insertTable(documentId, table)
andgetDocument(documentId, includeTabsContent = false)
are defined incomponents/google_docs/google_docs.app.mjs
as expected.- Consider enriching the export summary to surface table dimensions, insertion index, and tab context. For example:
- $.export("$summary", "Successfully inserted table"); + $.export( + "$summary", + `Inserted ${this.rows}×${this.columns} table at index ${this.index}` + + (this.tabId ? ` in tab ${this.tabId}` : "") + );
- Optional architecture tweak: introduce a boolean
returnUpdatedDocument
option (defaulttrue
) on the action. When set tofalse
, return the raw batchUpdate response instead of fetching the full document—this can reduce latency for callers that don’t need the updated content.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (16)
components/google_docs/actions/append-image/append-image.mjs
(1 hunks)components/google_docs/actions/append-text/append-text.mjs
(1 hunks)components/google_docs/actions/create-document-from-template/create-document-from-template.mjs
(1 hunks)components/google_docs/actions/create-document/create-document.mjs
(1 hunks)components/google_docs/actions/find-document/find-document.mjs
(1 hunks)components/google_docs/actions/get-document/get-document.mjs
(1 hunks)components/google_docs/actions/get-tab-content/get-tab-content.mjs
(1 hunks)components/google_docs/actions/insert-page-break/insert-page-break.mjs
(1 hunks)components/google_docs/actions/insert-table/insert-table.mjs
(1 hunks)components/google_docs/actions/insert-text/insert-text.mjs
(1 hunks)components/google_docs/actions/replace-image/replace-image.mjs
(1 hunks)components/google_docs/actions/replace-text/replace-text.mjs
(3 hunks)components/google_docs/google_docs.app.mjs
(2 hunks)components/google_docs/package.json
(1 hunks)components/google_docs/sources/new-document-created/new-document-created.mjs
(1 hunks)components/google_docs/sources/new-or-updated-document/new-or-updated-document.mjs
(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
components/google_docs/actions/insert-text/insert-text.mjs (1)
components/google_docs/actions/replace-text/replace-text.mjs (1)
text
(53-64)
components/google_docs/google_docs.app.mjs (2)
components/google_docs/actions/get-tab-content/get-tab-content.mjs (1)
tabs
(33-33)components/google_docs/actions/insert-table/insert-table.mjs (1)
table
(45-52)
🔇 Additional comments (14)
components/google_docs/package.json (1)
3-3
: Semver bump looks appropriate for new actions and app API additions.Moving from 0.4.4 → 0.5.0 matches the scope (new actions + app methods). No other changes spotted.
components/google_docs/sources/new-document-created/new-document-created.mjs (1)
8-8
: Version bump acknowledged; no functional changes detected.The source logic remains unchanged; version 0.0.4 → 0.0.5 aligns with the package release.
components/google_docs/actions/append-text/append-text.mjs (1)
7-7
: Version bump only — OK.No behavior change; version aligns with the package update.
components/google_docs/actions/replace-image/replace-image.mjs (1)
7-7
: Version bump only — OK.No behavior change detected.
components/google_docs/actions/get-document/get-document.mjs (1)
8-8
: Version bump acknowledged.Matches the coordinated release; no issues with the metadata.
components/google_docs/actions/create-document-from-template/create-document-from-template.mjs (1)
16-16
: Version bump only — looks good.No runtime or API surface changes beyond the version update.
components/google_docs/actions/append-image/append-image.mjs (1)
7-7
: Version bump acknowledged.No functional changes in this action. Safe to release.
components/google_docs/actions/find-document/find-document.mjs (1)
17-17
: Version increment approved.Behavior and public API remain unchanged.
components/google_docs/sources/new-or-updated-document/new-or-updated-document.mjs (1)
12-12
: Source version bump is fine.No logic changes; existing behavior is preserved.
components/google_docs/actions/create-document/create-document.mjs (1)
7-7
: Version bump only — looks goodThe version update to 0.1.7 aligns with the broader package/version cadence in this PR.
components/google_docs/actions/replace-text/replace-text.mjs (1)
38-50
: New tabIds prop is consistent with Docs Tabs supportAdding a multi-select tabIds prop to target specific tabs for replacement is aligned with the ReplaceAllTextRequest tabsCriteria capability. This expands functionality without breaking the existing API surface.
Docs confirm ReplaceAllTextRequest supports tabsCriteria with a list of tabIds. (developers.google.com)
components/google_docs/actions/insert-table/insert-table.mjs (3)
1-1
: Import path and app wiring look correct.The relative import to the app module is accurate for this directory layout.
6-6
: Confirmed documentation URL and feature support
- File components/google_docs/actions/insert-table/insert-table.mjs (line 6): the docs URL is correct (https://developers.google.com/workspace/docs/api/reference/rest/v1/documents/request#inserttablerequest).
InsertTableRequest
supports bothlocation.tabId
for inserting at a specific index within a tabbed segment andendOfSegmentLocation
(also with an optionaltabId
) for appending tables to the end of a segment.No changes required here.
34-42
: Verified:tabId
propDefinition contract matchesConfirmed that in
components/google_docs/google_docs.app.mjs
(lines 37–49), thetabId
entry underpropDefinitions
defines anoptions
function with signatureasync ({ documentId }) => { … }
, so the transform(c) => ({ documentId: c.docId })
correctly satisfies the expected{ documentId }
input.
Resolves #18045
New Actions
Updated Action
The ability to create tabs is being tracked in issue #17374.
Summary by CodeRabbit
New Features
Chores