Skip to content

Commit 57bf9f7

Browse files
authored
Merge pull request #429 from ryanfowler/markdown
Add markdown response body formatter
2 parents 1d30ebf + a47a008 commit 57bf9f7

9 files changed

Lines changed: 1727 additions & 3 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ A modern HTTP(S) client for the command line.
66

77
## Features
88

9-
- **Response formatting** - Automatic formatting and syntax highlighting for JSON, XML, YAML, HTML, CSS, CSV, MessagePack, Protocol Buffers, and more
9+
- **Response formatting** - Automatic formatting and syntax highlighting for JSON, XML, YAML, HTML, CSS, CSV, Markdown, MessagePack, Protocol Buffers, and more
1010
- **Image rendering** - Display images directly in your terminal
1111
- **WebSocket support** - Bidirectional WebSocket connections with automatic JSON formatting
1212
- **gRPC support** - Make gRPC calls with automatic JSON-to-protobuf conversion

docs/output-formatting.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,20 @@ Features:
137137
fetch example.com/styles.css
138138
```
139139

140+
### Markdown
141+
142+
**Content-Types**: `text/markdown`, `text/x-markdown`
143+
144+
Features:
145+
146+
- Syntax highlighting for headings, bold, italic, code spans, links, images
147+
- Fenced code block delegation to JSON, YAML, XML, HTML, CSS formatters
148+
- Blockquote and list marker highlighting
149+
150+
```sh
151+
fetch example.com/README.md
152+
```
153+
140154
### CSV
141155

142156
**Content-Types**: `text/csv`, `application/csv`

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/mattn/go-runewidth v0.0.19
1010
github.com/quic-go/quic-go v0.59.0
1111
github.com/tinylib/msgp v1.6.3
12+
github.com/yuin/goldmark v1.7.16
1213
golang.org/x/crypto v0.48.0
1314
golang.org/x/image v0.36.0
1415
golang.org/x/net v0.50.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
2424
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
2525
github.com/tinylib/msgp v1.6.3 h1:bCSxiTz386UTgyT1i0MSCvdbWjVW+8sG3PjkGsZQt4s=
2626
github.com/tinylib/msgp v1.6.3/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
27+
github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE=
28+
github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
2729
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
2830
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
2931
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=

internal/core/printer.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"io"
66
"os"
7+
"sync"
78
)
89

910
// Sequence represents an ANSI escape sequence.
@@ -61,7 +62,7 @@ func (h *Handle) Stdout() *Printer {
6162
// Printer allows for writing data with optional ANSI escape sequences based on
6263
// the color settings for a target.
6364
type Printer struct {
64-
file *os.File
65+
file io.Writer
6566
buf bytes.Buffer
6667
useColor bool
6768
}
@@ -81,6 +82,25 @@ func newPrinter(file *os.File, isTerm bool, c Color) *Printer {
8182
return &Printer{file: file, useColor: useColor}
8283
}
8384

85+
// TestPrinter returns a Printer suitable for testing. All output, including
86+
// flushed data, is captured and accessible via Bytes.
87+
func TestPrinter(useColor bool) *Printer {
88+
return &Printer{file: &lockedBuffer{}, useColor: useColor}
89+
}
90+
91+
// lockedBuffer is a goroutine-safe bytes.Buffer used as the flush target in
92+
// test printers so that Bytes can return the combined buffered + flushed data.
93+
type lockedBuffer struct {
94+
mu sync.Mutex
95+
buf bytes.Buffer
96+
}
97+
98+
func (lb *lockedBuffer) Write(p []byte) (int, error) {
99+
lb.mu.Lock()
100+
defer lb.mu.Unlock()
101+
return lb.buf.Write(p)
102+
}
103+
84104
// Set writes the provided Sequence.
85105
func (p *Printer) Set(s Sequence) {
86106
if p.useColor {
@@ -108,8 +128,17 @@ func (p *Printer) Discard() {
108128
p.buf.Reset()
109129
}
110130

111-
// Bytes returns the current contents of the buffer.
131+
// Bytes returns the current contents of the buffer. For test printers created
132+
// with TestPrinter, this also includes previously flushed data.
112133
func (p *Printer) Bytes() []byte {
134+
if lb, ok := p.file.(*lockedBuffer); ok {
135+
lb.mu.Lock()
136+
flushed := lb.buf.Bytes()
137+
lb.mu.Unlock()
138+
if len(flushed) > 0 {
139+
return append(flushed, p.buf.Bytes()...)
140+
}
141+
}
113142
return p.buf.Bytes()
114143
}
115144

internal/format/contenttype.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const (
1818
TypeHTML
1919
TypeImage
2020
TypeJSON
21+
TypeMarkdown
2122
TypeMsgPack
2223
TypeNDJSON
2324
TypeProtobuf
@@ -82,6 +83,8 @@ func GetContentType(headers http.Header) (ContentType, string) {
8283
return TypeCSV, charset
8384
case "html":
8485
return TypeHTML, charset
86+
case "markdown", "x-markdown":
87+
return TypeMarkdown, charset
8588
case "event-stream":
8689
return TypeSSE, charset
8790
case "xml":

0 commit comments

Comments
 (0)