This commit is contained in:
Taylor Wilsdon
2026-02-08 18:15:36 -05:00
parent 02a0d214e5
commit be6a42e6e5
4 changed files with 124 additions and 42 deletions

View File

@@ -283,21 +283,27 @@ def create_bullet_list_request(
end_index: int,
list_type: str = "UNORDERED",
nesting_level: int = None,
paragraph_start_indices: Optional[list[int]] = None,
) -> list[Dict[str, Any]]:
"""
Create requests to apply bullet list formatting with optional nesting.
The Google Docs API determines nesting level by counting leading tabs.
If nesting_level > 0, this function prepends tab characters before creating bullets.
Google Docs infers list nesting from leading tab characters. To set a nested
level, this helper inserts literal tab characters before each targeted
paragraph, then calls createParagraphBullets. This is a Docs API workaround
and does temporarily mutate content/index positions while the batch executes.
Args:
start_index: Start of text range to convert to list
end_index: End of text range to convert to list
list_type: Type of list ("UNORDERED" or "ORDERED")
nesting_level: Nesting level (0-8, where 0 is top level). If None or 0, no tabs added.
paragraph_start_indices: Optional paragraph start positions for ranges with
multiple paragraphs. If omitted, only start_index is tab-prefixed.
Returns:
List of request dictionaries (insertText for tabs if needed, then createParagraphBullets)
List of request dictionaries (insertText for nesting tabs if needed,
then createParagraphBullets)
"""
bullet_preset = (
"BULLET_DISC_CIRCLE_SQUARE"
@@ -314,19 +320,39 @@ def create_bullet_list_request(
requests = []
# Insert tabs for nesting if needed (nesting_level > 0)
# Insert tabs for nesting if needed (nesting_level > 0).
# For multi-paragraph ranges, callers should provide paragraph_start_indices.
if nesting_level and nesting_level > 0:
tabs = "\t" * nesting_level
requests.append(
{
"insertText": {
"location": {"index": start_index},
"text": tabs,
paragraph_starts = paragraph_start_indices or [start_index]
paragraph_starts = sorted(set(paragraph_starts))
if any(not isinstance(idx, int) for idx in paragraph_starts):
raise ValueError("paragraph_start_indices must contain only integers")
original_start = start_index
original_end = end_index
inserted_char_count = 0
for paragraph_start in paragraph_starts:
adjusted_start = paragraph_start + inserted_char_count
requests.append(
{
"insertText": {
"location": {"index": adjusted_start},
"text": tabs,
}
}
}
)
inserted_char_count += nesting_level
# Keep createParagraphBullets range aligned to the same logical content.
start_index += (
sum(1 for idx in paragraph_starts if idx < original_start) * nesting_level
)
end_index += (
sum(1 for idx in paragraph_starts if idx < original_end) * nesting_level
)
# Adjust end_index to account for inserted tabs
end_index += nesting_level
# Create the bullet list
requests.append(