Skip to content

id(web): saving a .txt file silently deletes every list, quote, code block and table #1306

Closed

Description

@dezren39

id(web): saving a .txt file silently deletes every list, quote, code block and table

Summary

A .txt document is edited in the full rich editor, but the save path
extracts only paragraph and heading text. Every other block the editor
allows — bullet/ordered/task lists, blockquotes, code blocks, tables,
horizontal rules — is silently deleted on save, with a success
response. This is unrecoverable data loss for any .txt file whose
author used the toolbar, markdown shortcuts, paste, or a collab peer's
edit to create a non-paragraph block.

Evidence

  • Editor side: pkgs/id/web/src/editor.ts:288-289 — getSchema(mode)
    returns richSchema for every mode except raw, and :295
    hasToolbar includes plain. The file comment at :42 says the
    full schema (lists, GFM task lists, tables) applies to
    "rich/markdown/plain modes". So a .txt doc legitimately contains
    any block type.
  • Save side: pkgs/id/src/web/routes.rs:1976 convert_doc_to_bytes
    routes .txt (ContentMode::Plain) to extract_plain_text
    (routes.rs:2009). That function handles only paragraph and
    heading at the top level; the catch-all arm at routes.rs:2049
    is _ => {} — every other node is dropped without a log, error, or
    placeholder. (Inline non-text nodes are likewise dropped at :2032.)
  • Verified this run on origin/main 90f7ea0 with a probe crate holding
    the verbatim extract_plain_text body (log:
    hidden_files/probe-2026-10-26-2352/out4.log): a doc containing
    paragraph "intro", a 2-item bullet list, a blockquote, a code block,
    a table cell and a paragraph "outro" extracted to exactly
    "intro\noutro" — the list items, quote, code and cell text all
    vanished.

Why it matters

Silent, success-reported deletion is the worst failure class for a
documents app: the user only discovers the loss on the next open, and
by then the saved bytes are the only copy. The heading arm shows the
authors already knew non-paragraph blocks reach this function; the
remaining block types were simply never handled.

Acceptance criteria

  • Saving a .txt doc containing lists, blockquote, code block, table
    or horizontal rule no longer silently discards their text: either
    the text is extracted in a documented plain-text rendering (e.g.
    list item text per line, cell text per line), or the save fails
    loudly for docs it cannot represent — pick one policy, document it
    on convert_doc_to_bytes, and pin it with tests.
  • A regression test in the web routes/markdown test suite covers at
    least: bullet list, blockquote, code block, table — asserting the
    saved .txt bytes contain their text (or the save errors, per the
    chosen policy).
  • Paragraph/heading-only .txt docs save byte-identically to today.
  • The markdown (.md) and raw save paths are unchanged.

Suggested direction

Recursive text extraction over block children (list_item → its
paragraphs, blockquote → its blocks, table rows/cells → their
paragraphs, code_block → its text) is the smallest change that makes
.txt save loss-free for text content; formatting marks/structure
are inherently lost in plain text, text must not be.

Activity

  1. developing-today commented on Oct 27, 2026

    @developing-today
    Contributor
  2. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/highImportant and time-sensitive
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    effort/sSmall: expected under 2 hours of work
    on Oct 27, 2026
  3. dezren39 commented on Oct 27, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · state: filed

    • Agent: new-issue-creator job
    • Session / ID: new-issue-creator run, 2026-10-27T05:31Z
    • Found via: filed this run
    • Task: Filed after verifying on origin/main 90f7ea0 that extract_plain_text (routes.rs:2009) drops every non-paragraph/heading block on .txt save while the plain editor uses the full rich schema (editor.ts:288-289).
    • Expectation: effort s — triage picks the loss-free extraction (or loud-failure) policy, then a small fix with regression tests.
    • Links: probe log hidden_files/probe-2026-10-26-2352/out4.log; queue packet packet-1306.json (repo-health-code-pilot)
  4. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed on Oct 27, 2026
  5. 39 remaining items

  6. added
    status/parkedDeliberately paused with a recorded resume condition
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Oct 27, 2026
  7. added a commit that references this issue on Oct 27, 2026
  8. dezren39 commented on Oct 27, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

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

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)effort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/highImportant and time-sensitivesource/creatorFiled by the new-issue-creator jobstatus:donetask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions