From 6300d9b8a808d8778b7c087f31ece0eaf896fc0b Mon Sep 17 00:00:00 2001
From: Andrew Nesbitt
Date: Mon, 19 Oct 2026 08:37:49 +0100
Subject: [PATCH 1/2] Keep pod2html cache file out of the working directory
---
external.go | 16 +++++++++++-----
markup.go | 6 +++---
markup_test.go | 25 +++++++++++++++++++++++++
3 files changed, 39 insertions(+), 8 deletions(-)
diff --git a/external.go b/external.go
index 775ae54..f607a5d 100644
--- a/external.go
+++ b/external.go
@@ -34,7 +34,7 @@ type InputMode int
const (
InputStdin InputMode = iota // Pass content via stdin (default).
- InputTempFile // Write to a temp file, replace {file} in args.
+ InputTempFile // Write to a temp file, replace {file} and {dir} in args.
)
const defaultTimeout = 30 * time.Second
@@ -45,7 +45,7 @@ const maxOutputSize = 2 * 1024 * 1024
// ExternalConfig configures an external renderer.
type ExternalConfig struct {
Command string // Command to execute.
- Args []string // Arguments. Use {file} as a placeholder for temp file path.
+ Args []string // Arguments. {file} is the temp file path, {dir} a per-render scratch directory.
InputMode InputMode // How to pass content to the command.
Timeout time.Duration // Command timeout. Zero means 30s default.
BodyPattern string // Regex to extract body from full HTML output. Empty means use full output.
@@ -128,11 +128,16 @@ func (r *ExternalRenderer) renderWithTempFile(content []byte) (string, error) {
ext = "." + r.config.Command
}
- f, err := os.CreateTemp("", "markup-*"+ext)
+ dir, err := os.MkdirTemp("", "markup-*")
+ if err != nil {
+ return "", err
+ }
+ defer func() { _ = os.RemoveAll(dir) }()
+
+ f, err := os.CreateTemp(dir, "markup-*"+ext)
if err != nil {
return "", err
}
- defer func() { _ = os.Remove(f.Name()) }()
if _, err := f.Write(content); err != nil {
_ = f.Close()
@@ -142,7 +147,8 @@ func (r *ExternalRenderer) renderWithTempFile(content []byte) (string, error) {
args := make([]string, len(r.config.Args))
for i, arg := range r.config.Args {
- args[i] = strings.ReplaceAll(arg, "{file}", f.Name())
+ arg = strings.ReplaceAll(arg, "{file}", f.Name())
+ args[i] = strings.ReplaceAll(arg, "{dir}", dir)
}
ctx, cancel := context.WithTimeout(context.Background(), r.timeout)
diff --git a/markup.go b/markup.go
index b70f1b0..3cd77f8 100644
--- a/markup.go
+++ b/markup.go
@@ -137,9 +137,9 @@ func NewDefaultRegistry() *Registry {
".rst", ".rest")
r.Register(FormatPod, NewExternalRenderer(ExternalConfig{
- Command: "pod2html",
- InputMode: InputTempFile,
- Args: []string{"--infile={file}", "--quiet"},
+ Command: "pod2html",
+ InputMode: InputTempFile,
+ Args: []string{"--infile={file}", "--cachedir={dir}", "--quiet"},
BodyPattern: `(?s)]*>\s*(.*?)\s*`,
}), ".pod")
diff --git a/markup_test.go b/markup_test.go
index ec9ad69..eeab034 100644
--- a/markup_test.go
+++ b/markup_test.go
@@ -520,6 +520,7 @@ func TestRenderPod(t *testing.T) {
t.Skip("pod2html not installed")
}
content := readTestdata(t, "README.pod")
+ t.Chdir(t.TempDir())
result, err := r.Render("README.pod", content)
if err != nil {
t.Fatalf("unexpected error: %v", err)
@@ -533,6 +534,13 @@ func TestRenderPod(t *testing.T) {
if strings.Contains(result.HTML, "hi
"))
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if html != "hi
" {
+ t.Errorf("html = %q, want %q", html, "hi
")
+ }
+}
+
// --- RendererFunc ---
func TestRendererFunc(t *testing.T) {
From 74f961486ce33dd0069629bef904a2d6615a6617 Mon Sep 17 00:00:00 2001
From: Andrew Nesbitt
Date: Mon, 19 Oct 2026 08:40:34 +0100
Subject: [PATCH 2/2] Run gofmt on external.go
---
external.go | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/external.go b/external.go
index f607a5d..ddc9840 100644
--- a/external.go
+++ b/external.go
@@ -15,9 +15,9 @@ import (
// limitedWriter wraps a writer and returns an error if the limit is exceeded.
type limitedWriter struct {
- w io.Writer
- n int
- limit int
+ w io.Writer
+ n int
+ limit int
}
func (lw *limitedWriter) Write(p []byte) (int, error) {
@@ -230,7 +230,7 @@ func rstRender(content []byte) (string, error) {
// toolCache caches which external tools are available.
var (
- toolCache sync.Map
+ toolCache sync.Map
)
func toolAvailable(name string) bool {