Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Requires Go (see `go.mod`/`mise.toml` for version) and, for packaging, `just`, `

Everything happens in `main()` in `main.go`, in a straight-line pipeline:

1. **Flag parsing** — `-o`, `-v/-version`, `-h/-help`, `-b/-bare`. First positional arg is the input markdown file.
1. **Flag parsing** — `-o`, `-v/-version`, `-h/-help`, `-b/-bare`. First positional arg is the input markdown file; a single `-` reads the markdown from stdin instead, in which case `baseDir` for image resolution is the working directory rather than the input file's directory.
2. **Image inlining** (`processMarkdownImages` → `processHTMLImages`/markdown image regex + `imageToDataURI`) — rewrites relative image references (both `![]()` markdown syntax and raw `<img src=...>` HTML) into base64 `data:` URIs *before* markdown parsing, so the output HTML is fully self-contained/offline-viewable. This includes path-traversal guards (caps `..` traversal depth) and a 10MB per-image size cap.
3. **Markdown parsing** via Goldmark, configured with:
- `extension.GFM` (tables, task lists, strikethrough, etc.)
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ A lightweight command-line tool that converts markdown files to styled HTML and

## Usage

Pass a filename, or a single dash to read markdown from standard input:

```sh
mdview notes.md
cat notes.md | mdview -
age -d -i ~/.config/age/key.txt notes.md.age | mdview -
```

Reading from standard input avoids writing the markdown to disk first,
which is useful when the content is decrypted or generated on the fly.
Relative image paths are then resolved against the current working
directory.

By default, `mdview` writes the generated HTML to a temporary directory.
It tries these in order:
- A path defined in the `MDVIEW_DIR` environment variable
Expand Down
21 changes: 17 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"errors"
"flag"
"fmt"
"io"
"io/fs"
"log"
"os"
Expand Down Expand Up @@ -59,16 +60,28 @@ func main() {
}

if inputFilename == "" || *helpPtr {
os.Stderr.WriteString("Usage:\nmdview [options] <filename>\nFormats markdown and launches it in a browser.\nIf the environment variable MDVIEW_DIR is set, the temporary file will be written there.\n")
os.Stderr.WriteString("Usage:\nmdview [options] <filename>\nFormats markdown and launches it in a browser.\nUse - as the filename to read markdown from standard input.\nIf the environment variable MDVIEW_DIR is set, the temporary file will be written there.\n")
flag.PrintDefaults()
os.Exit(1)
}

dat, err := os.ReadFile(inputFilename)
check(err)
// A filename of - means read the markdown from standard input. Relative image
// paths are then resolved against the working directory, as there is no input
// file to anchor them to.
var dat []byte
var err error
baseDir := "."

if inputFilename == "-" {
dat, err = io.ReadAll(os.Stdin)
check(err)
} else {
dat, err = os.ReadFile(inputFilename)
check(err)
baseDir = filepath.Dir(inputFilename)
}

// Convert relative image links to data URIs in the markdown source
baseDir := filepath.Dir(inputFilename)
processedMarkdown := processMarkdownImages(string(dat), baseDir)
processedBytes := []byte(processedMarkdown)

Expand Down
5 changes: 5 additions & 0 deletions mdview.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# SYNOPSIS

**mdview** _filename_
**mdview** **-**
**mdview** \[**-h**|**--help**|**-v**|**--version**]

# DESCRIPTION
Expand All @@ -16,6 +17,10 @@ then launches that file in the default web browser. By default, it will
use the operating system's default temporary directory unless the
environment variable MDVIEW_DIR is set.

If _filename_ is a single dash (**-**), the markdown is read from
standard input. Relative image paths are then resolved against the
current working directory.

## Options

**-b**, **-bare**
Expand Down
Loading