Skip to content

--attach stack 3/8: Rewrite markdown references to uploaded assets - #14179

Merged
BagToad merged 2 commits into
bagtoad/attach-file-validationfrom
bagtoad/attach-markdown-rewriting
Aug 25, 2026
Merged

--attach stack 3/8: Rewrite markdown references to uploaded assets#14179
BagToad merged 2 commits into
bagtoad/attach-file-validationfrom
bagtoad/attach-markdown-rewriting

Conversation

@BagToad

@BagToad BagToad commented Aug 18, 2026

Copy link
Copy Markdown
Member

Part of the pull request stack tracked in #14186.

Description

This is the third layer of the stack, and the largest and hardest pull request in it. Nothing here is reachable from a command yet.

Given some markdown and a set of attached files, it finds every reference in the markdown that points at one of those files and rewrites the destination to the uploaded URL. It reports which attachments were never referenced, so the caller can append them.

The code runs in three phases, and it is ordered that way on purpose:

  1. Find every reference. The markdown is parsed with goldmark, the parser gh already depends on, and each link or image node is asked for its position.
  2. Plan the edits. Each reference becomes a byte range and a replacement.
  3. Apply the edits, working back to front so the earlier ranges stay valid.

The behaviour that follows from that:

  • A reference style definition is rewritten once, at the definition, so every use of that label follows from one edit.
  • A path inside a code fence or an inline code span is left exactly as written.
  • A plain link stays a link. Only the destination moves, so alt text, titles and formatting inside the label survive.
  • A video embedded alone on its own line has the whole node replaced by a bare URL, because that is what GitHub needs to render a player. A video embedded inline degrades to a link instead, since a player cannot render in the middle of a sentence.
  • A video written as a reference style image is refused, because rewriting it would produce an image tag pointing at a video.
  • The same file referenced twice is uploaded once and both references get the same URL.

The second commit adds one markdown document that exercises every syntax the package handles, together with its expected output.

How did you test this change?

The whole stack was built and each of the behaviours above was exercised by hand against a private test repository. That covered a reference rewritten in place, a reference style definition with two uses following one edit, a fenced block and an inline code span left untouched, a plain link staying a link, a video alone on a line becoming a bare URL, a video inline becoming a link, a video as a reference style image being refused, an unused definition left alone, a file named in the body but never attached left alone, and the same file referenced twice sharing one uploaded asset.

Key points

About 110 lines of this are hand written byte scanning. It exists because goldmark reports the position of a node but not the position of the destination inside that node.

The alternative would be to re-render the document from the parsed tree. That would be worse, because it normalises the author's own prose, and someone who wrote a comment by hand should get their comment back rather than a reformatted version of it. A follow up can restructure this around goldmark's node identity and delete some of the scanning. That work is not here.

Notes for reviewers

Start with the two entry points and read the three phases in order.

The fixture document in the second commit is the fastest way to understand the behaviour. Reading the input and the expected output side by side shows what the package does without reading the scanner at all, which is why it is a separate commit.

Authorship and follow-up

Who wrote this:

  • A human wrote it.
  • An agent wrote it under close human direction.
  • An agent wrote it independently, and no human has guided the implementation beyond the initial prompt.

Who answers review comments:

  • @BagToad will read and reply directly. Name the account.
  • An agent will draft replies and @BagToad will read them before they are posted.
  • Nobody has explicitly committed to replying.

@BagToad BagToad changed the title bagtoad/attach markdown rewriting --attach stack 3/8: Rewrite markdown references to uploaded assets Aug 18, 2026
@BagToad
BagToad marked this pull request as ready for review August 18, 2026 05:56
@BagToad
BagToad requested a review from a team as a code owner August 18, 2026 05:56
@BagToad
BagToad requested review from babakks and a balanced review from Copilot August 18, 2026 05:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds internal markdown reference rewriting for uploaded attachments.

Changes:

  • Parses and matches attachment references using Goldmark.
  • Rewrites image, video, and reference-style destinations.
  • Adds comprehensive unit and fixture coverage.
Show a summary per file
File Description
internal/attachments/references.go Implements reference scanning and rewriting.
internal/attachments/references_test.go Tests rewriting behavior and edge cases.
internal/attachments/references_fixture_test.go Adds fixture-based regression testing.
internal/attachments/testdata/references_input.md Provides comprehensive fixture input.
internal/attachments/testdata/references_expected.md Defines expected rewritten output.

Review details

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 5/5 changed files
  • Comments generated: 4
  • Review effort level: Balanced

Comment thread internal/attachments/references.go
Comment thread internal/attachments/references.go
Comment thread internal/attachments/references.go
Comment thread internal/attachments/references_test.go
@BagToad BagToad mentioned this pull request Aug 18, 2026
BagToad and others added 2 commits August 18, 2026 08:55
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

@babakks babakks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for this one, @BagToad! 🙏

The byte-scanning rewriter is careful work, and the reference-style handling (definitions, collapsed/shortcut forms, code-fence exclusion) covers a lot of tricky ground. I left a batch of comments, but they're all nitpicks, questions, and test-coverage suggestions, nothing blocking.

A few themes:

  • One forward-compat nit: the update test flag is quite generic given go test accepts many flags, so a more specific name like update-md-fixture would be safer.
  • A couple of "four cells" comments left me wondering if some mental grouping didn't make it into the code.

Nothing here needs to hold up the stack. Happy to re-look once you've had a chance to go through them.

Comment thread internal/attachments/references_fixture_test.go
Comment thread internal/attachments/references_fixture_test.go
Comment thread internal/attachments/references_test.go
Comment thread internal/attachments/references_test.go
Comment thread internal/attachments/references_test.go
Comment thread internal/attachments/references_test.go
Comment thread internal/attachments/references_test.go

@babakks babakks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Now, I'm also thinking what if a user uses Windows style in their Markdown?

![alt](.\login.png)

Do we already cover that case?

Update: maybe we can extend the candidates slice with these. 🤔

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants