Preview
Preview Any Document: Multi-Format HTML with Dark/Light Mode
If you work a lot in the terminal and write a lot of markdown specs, LaTeX, or other markup formats, you know how convenient it is to quickly see a rendered version of your work. Here’s a nice tool to do this within a terminal.
Why This Matters
Writers, developers, and researchers often deal with multiple file formats:
- Markdown (
.md) for notes or blogs - LaTeX (
.tex) for academic papers - ReStructuredText (
.rst) for documentation - AsciiDoc (
.adoc) or Org-mode (.org) for project notes - HTML for raw web content
Switching between editors, browsers, and PDF exporters can be tedious. The goal is simple: write once, preview everywhere, instantly.
Requirements
Make sure Pandoc is installed:
sudo pacman -S pandoc
Save your dark/light templates somewhere (e.g., ~/.pandoc/templates/professional-dark.html)
Some example templates are at the end.
Set environment variables:
export PREVIEW_DARK_TEMPLATE_FILE="$HOME/.pandoc/templates/professional-dark.html"
export PREVIEW_LIGHT_TEMPLATE_FILE="$HOME/.pandoc/templates/professional-light.html"
Add the preview function to your .bashrc or .zshrc
And you’re ready to preview any document, anytime.
preview function
## takes a file for input and opens the styled html output in a browser with xdg-open
preview() {
if [[ $# -lt 1 ]]; then
echo "Usage: mdpreview [-d|-l] <file1.md> [file2.md ...]"
echo " -d dark mode (default)"
echo " -l light mode"
return 1
fi
local mode="dark"
local files=()
# check for mode flag
if [[ "$1" == "-d" ]]; then
mode="dark"
shift
elif [[ "$1" == "-l" ]]; then
mode="light"
shift
fi
if [[ $# -lt 1 ]]; then
echo "No Markdown files provided."
return 1
fi
local template_file
if [[ "$mode" == "dark" ]]; then
template_file="${MARKDOWN_DARK_TEMPLATE_FILE:-$HOME/.pandoc/templates/professional-dark.html}"
else
template_file="${MARKDOWN_LIGHT_TEMPLATE_FILE:-$HOME/.pandoc/templates/professional-light.html}"
fi
for input in "$@"; do
if [[ ! -f "$input" ]]; then
echo "File not found: $input"
continue
fi
local filename=$(basename "$input")
local name="${filename%.md}"
local output="/tmp/${name}.html"
pandoc --standalone \
--metadata title="$name" \
--template="$template_file" \
"$input" > "$output" || { echo "Failed: $input"; continue; }
echo "Opened: $output"
xdg-open "$output"
done
}
This shell function lets you:
- Open one or multiple files at once
- Automatically generate an HTML file in
/tmp - Use dark or light mode templates for readability
Usage
# Preview a single file (dark mode by default)
preview my_notes.md
# Preview multiple files
preview chapter1.md chapter2.md chapter3.md
# Use light mode
preview -l chapter1.md chapter2.md
What’s Under the Hood
The function uses Pandoc, combined with custom HTML templates. The templates include:
- A constrained width wrapper for comfortable reading
- Consistent typography for headings, paragraphs, lists, code blocks, tables, and blockquotes
- Dark/light color schemes for eye comfort
- Syntax highlighting for code snippets
Multi-Format Support
Because Pandoc supports dozens of formats, you can preview almost anything:
- Markdown (.md)
- ReStructuredText (.rst)
- AsciiDoc (.adoc)
- Org-mode (.org)
- HTML (.html)
- LaTeX (.tex)
Templates
- Dark
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>$title$</title>
<style>
/* ================================
Dark Mode Styles
================================ */
:root {
--bg: #1f2328;
--surface: #24292f;
--border: #30363d;
--text: #e6edf3;
--text-muted: #9da7b3;
--heading: #f0f6fc;
--accent: #4ea1ff;
--code-bg: #2b3137;
--quote-border: #3b434b;
--radius: 6px;
}
html { font-size: 16px; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.7;
}
.doc-wrapper {
display: flex;
justify-content: center;
padding: 3rem 1.5rem 4rem;
}
.doc { width: 100%; max-width: 780px; }
p, ul, ol, blockquote, pre, table { margin-bottom: 1.6rem; }
h1, h2, h3, h4, h5, h6 {
margin-top: 2.4rem;
margin-bottom: 0.8rem;
font-weight: 600;
color: var(--heading);
line-height: 1.3;
}
h1, h2 { border-bottom: 1px solid var(--border); padding-bottom: 0.4rem; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
blockquote {
padding: 0.8rem 1rem;
border-left: 4px solid var(--quote-border);
background: var(--surface);
border-radius: var(--radius);
color: var(--text-muted);
}
code {
font-family: ui-monospace, monospace;
background: var(--code-bg);
padding: 0.2em 0.4em;
border-radius: 4px;
font-size: 0.9em;
}
pre {
background: var(--code-bg);
padding: 1rem;
border-radius: var(--radius);
overflow-x: auto;
}
table { width: 100%; border-collapse: collapse; }
th, td { padding: 0.6rem 0.8rem; border-bottom: 1px solid var(--border); }
th { text-align: left; font-weight: 600; color: var(--heading); }
tr:last-child td { border-bottom: none; }
hr { border: 0; border-top: 1px solid var(--border); margin: 2.5rem 0; }
strong { font-weight: 600; color: var(--heading); }
em { font-style: italic; color: #d2dbe3; }
img { max-width: 100%; height: auto; border-radius: var(--radius); display: block; margin: 1.6rem 0; }
::selection { background: rgba(78, 161, 255, 0.35); }
$if(highlighting-css)$
$highlighting-css$
$endif$
</style>
</head>
<body>
<div class="doc-wrapper">
<article class="doc">
$body$
</article>
</div>
</body>
</html>
- Light
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>$title$</title>
<style>
/* ================================
Light Mode Styles
================================ */
:root {
--bg: #fafbfc;
--surface: #ffffff;
--border: #d0d7de;
--text: #24292f;
--text-muted: #57606a;
--heading: #111827;
--accent: #0366d6;
--code-bg: #f6f8fa;
--quote-border: #d0d7de;
--radius: 6px;
}
html { font-size: 16px; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.7;
}
.doc-wrapper {
display: flex;
justify-content: center;
padding: 3rem 1.5rem 4rem;
}
.doc { width: 100%; max-width: 780px; }
p, ul, ol, blockquote, pre, table { margin-bottom: 1.6rem; }
h1, h2, h3, h4, h5, h6 {
margin-top: 2.4rem;
margin-bottom: 0.8rem;
font-weight: 600;
color: var(--heading);
line-height: 1.3;
}
h1, h2 { border-bottom: 1px solid var(--border); padding-bottom: 0.4rem; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
blockquote {
padding: 0.8rem 1rem;
border-left: 4px solid var(--quote-border);
background: var(--surface);
border-radius: var(--radius);
color: var(--text-muted);
}
code {
font-family: ui-monospace, monospace;
background: var(--code-bg);
padding: 0.2em 0.4em;
border-radius: 4px;
font-size: 0.9em;
}
pre {
background: var(--code-bg);
padding: 1rem;
border-radius: var(--radius);
overflow-x: auto;
}
table { width: 100%; border-collapse: collapse; }
th, td { padding: 0.6rem 0.8rem; border-bottom: 1px solid var(--border); }
th { text-align: left; font-weight: 600; color: var(--heading); }
tr:last-child td { border-bottom: none; }
hr { border: 0; border-top: 1px solid var(--border); margin: 2.5rem 0; }
strong { font-weight: 600; color: var(--heading); }
em { font-style: italic; color: #333; }
img { max-width: 100%; height: auto; border-radius: var(--radius); display: block; margin: 1.6rem 0; }
::selection { background: rgba(3, 102, 214, 0.25); }
$if(highlighting-css)$
$highlighting-css$
$endif$
</style>
</head>
<body>
<div class="doc-wrapper">
<article class="doc">
$body$
</article>
</div>
</body>
</html>