diff --git a/CLAUDE.md b/CLAUDE.md
index db99807..2ae0ac5 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -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 `
` 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.)
diff --git a/README.md b/README.md
index 472bce0..b416b7e 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/main.go b/main.go
index 4d028d3..7250eb7 100644
--- a/main.go
+++ b/main.go
@@ -9,6 +9,7 @@ import (
"errors"
"flag"
"fmt"
+ "io"
"io/fs"
"log"
"os"
@@ -59,16 +60,28 @@ func main() {
}
if inputFilename == "" || *helpPtr {
- os.Stderr.WriteString("Usage:\nmdview [options] \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] \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)
diff --git a/mdview.1.md b/mdview.1.md
index 30ac148..67d3f43 100644
--- a/mdview.1.md
+++ b/mdview.1.md
@@ -7,6 +7,7 @@
# SYNOPSIS
**mdview** _filename_
+**mdview** **-**
**mdview** \[**-h**|**--help**|**-v**|**--version**]
# DESCRIPTION
@@ -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**