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**