Skip to content

bug(docs write --tab): markdown path drops nested-list nesting (children render as plain text) #696

Description

@sebsnyk

Symptom

gog docs write --replace --markdown --tab=<id> does not preserve nested-list nesting from the input markdown. Child items at indent level 1+ collapse into the parent's paragraph as plain text with literal - (or * / 1. ) prefixes, instead of being emitted as Docs list paragraphs with bullet.nestingLevel = 1, 2, ….

The same markdown round-trips correctly through gog docs create --file and through gog docs write --replace --markdown without --tab. Only the per-tab path drops the nesting step.

Adjacent prior art on the same path: #644 (blank-line collapse on --replace --markdown --tab, since closed). Same code path, similar shape — markdown semantics that the non-tab converter handles get dropped by the per-tab converter.

Reproducer (fully public)

Public test doc: https://docs.google.com/document/d/1y-zHKNOooMRRObDL3JI9iYqC874_xYY1S-xV3mWbDQQ/edit

The doc has two tabs containing the same input markdown:

  • Tab 1 ("Tab 1") was populated via gog docs create --file test.md and then re-pushed via gog docs write --replace --markdown --file test.md (no --tab). Nested bullets render correctly: 3 levels deep, Docs bullet glyphs change (• → ◦ → ▪), nestingLevel is set per item.
  • Tab 2 ("Tab 2 nested test") was populated via gog docs write --replace --markdown --tab=t.88hfk0y0qgnb --file test.md. The same nested-bullet input produces flat output: every parent becomes * Parent X, every child becomes a plain-text line with literal - Child X.1 inside the parent's paragraph.

The input markdown covered six variants in one file: 2-space-dash, 4-space-dash, tab-dash, 2-space-asterisk, ordered, and mixed (ordered parent + unordered children). All six variants pass on tab 1 and fail identically on tab 2 — so the bug is not an indent-style mismatch; the per-tab converter is dropping the list-nesting step wholesale.

Verification

gog docs raw <docId> (which returns tab 0 only — note that --tab is missing on raw, separate gap) on tab 1 shows correct bullet.nestingLevel = 1, 2 per child:

L0: Parent A1
L1:   Child A1.1
L1:   Child A1.2
L2:     Grandchild A1.2.a

gog docs export <docId> --format=md --tab=t.88hfk0y0qgnb on tab 2 shows what actually landed — children as soft-line-broken plain text with escaped dashes:

* Parent A1

  \- Child A1.1
  \- Child A1.2
    \- Grandchild A1.2.a

* Parent A2

Notice the parent is a real list paragraph (* Parent A1) but the children are inside the parent's paragraph as continuation lines with literal \- escapes — i.e. the converter treated the indented dashes as escaped literal text rather than nested-list markers.

Expected behaviour

--tab=<id> markdown writes should preserve nested-list nesting with the same semantics as the non-tab path. Specifically:

  1. All four indent conventions tested (2-space, 4-space, tab, mixed) produce bullet.nestingLevel matching the indent depth.
  2. Both unordered (-, *) and ordered (1., 2.) parents support nested children of either kind.
  3. Nesting is preserved up to the maximum depth Google Docs itself supports (10 levels per the Docs API list-style spec — see https://developers.google.com/workspace/docs/api/reference/rest/v1/documents#Bullet). The current per-tab path appears to support level 0 only.

Acceptance criteria

  • The exact input markdown that produces 3-level nesting in gog docs create / gog docs write --replace --markdown (no --tab) also produces 3-level nesting via gog docs write --replace --markdown --tab=<id>.
  • gog docs export --format=md --tab=<id> round-trips the nested structure (children appear as proper indented list items in the exported markdown, not as soft-line-broken paragraph text with escaped dashes).
  • A 10-level-deep input list (the Docs API's documented unordered-list nesting limit) produces all 10 levels with correct nestingLevel, not a flattened paragraph.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal priority bug or improvement with limited blast radius.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:queueable-fixClawSweeper marked this issue as an existing queue_fix_pr work candidate.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:data-lossThis issue is about lost, corrupted, or silently dropped user/session/config data.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions