forked from haffizaliraza/rust-md2html
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathREADME.html
More file actions
191 lines (185 loc) · 19.6 KB
/
Copy pathREADME.html
File metadata and controls
191 lines (185 loc) · 19.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="mdo 0.6.1">
<title>Open Markdown as HTML</title>
<style>
:root{--sans-font:-apple-system,BlinkMacSystemFont,"Avenir Next",Avenir,"Nimbus Sans L",Roboto,"Noto Sans","Segoe UI",Arial,Helvetica,"Helvetica Neue",sans-serif;--mono-font:Consolas,Menlo,Monaco,"Andale Mono","Ubuntu Mono",monospace;--standard-border-radius:5px;--border-width:1px;--bg:#fff;--accent-bg:#f5f7ff;--text:#212121;--text-light:#585858;--border:#898ea4;--accent:#0d47a1;--accent-hover:#1266e2;--accent-text:var(--bg);--code:#d81b60;--preformatted:#444;--marked:#fd3;--disabled:#efefef}@media (prefers-color-scheme:dark){:root{color-scheme:dark;--bg:#212121;--accent-bg:#2b2b2b;--text:#dcdcdc;--text-light:#ababab;--accent:#ffb300;--accent-hover:#ffe099;--accent-text:var(--bg);--code:#f06292;--preformatted:#ccc;--disabled:#111}img,video{opacity:.8}}*,:before,:after{box-sizing:border-box}textarea,select,input,progress{-webkit-appearance:none;-moz-appearance:none;appearance:none}html{font-family:var(--sans-font);scroll-behavior:smooth}body{color:var(--text);background-color:var(--bg);grid-template-columns:1fr min(45rem,90%) 1fr;margin:0;font-size:1.15rem;line-height:1.5;display:grid}body>*{grid-column:2}body>header{background-color:var(--accent-bg);border-bottom:var(--border-width)solid var(--border);text-align:center;grid-column:1/-1;padding:0 .5rem 2rem}body>header>:only-child{margin-block-start:2rem}body>header h1{max-width:1200px;margin:1rem auto}body>header p{max-width:40rem;margin:1rem auto}main{padding-top:1.5rem}body>footer{color:var(--text-light);text-align:center;border-top:var(--border-width)solid var(--border);margin-top:4rem;padding:2rem 1rem 1.5rem;font-size:.9rem}h1{font-size:3rem}h2{margin-top:3rem;font-size:2.6rem}h3{margin-top:3rem;font-size:2rem}h4{font-size:1.44rem}h5{font-size:1.15rem}h6{font-size:.96rem}p{margin:1.5rem 0}p,h1,h2,h3,h4,h5,h6{overflow-wrap:break-word}h1,h2,h3{line-height:1.1}@media only screen and (width<=720px){h1{font-size:2.5rem}h2{font-size:2.1rem}h3{font-size:1.75rem}h4{font-size:1.25rem}}a,a:visited{color:var(--accent)}a:hover{text-decoration:none}button,.button,a.button,input[type=submit],input[type=reset],input[type=button]{border:var(--border-width)solid var(--accent);background-color:var(--accent);color:var(--accent-text);padding:.5rem .9rem;line-height:normal;text-decoration:none}.button[aria-disabled=true],input:disabled,textarea:disabled,select:disabled,button[disabled]{cursor:not-allowed;background-color:var(--disabled);border-color:var(--disabled);color:var(--text-light)}input[type=range]{padding:0}abbr[title]{cursor:help;text-decoration-line:underline;text-decoration-style:dotted}button:enabled:hover,.button:not([aria-disabled=true]):hover,input[type=submit]:enabled:hover,input[type=reset]:enabled:hover,input[type=button]:enabled:hover{background-color:var(--accent-hover);border-color:var(--accent-hover);cursor:pointer}.button:focus-visible,button:focus-visible:where(:enabled),input:enabled:focus-visible:where([type=submit],[type=reset],[type=button]){outline:2px solid var(--accent);outline-offset:1px}header nav{padding:1rem 0 0;font-size:1rem;line-height:2}header nav ul,header nav ol{flex-flow:wrap;place-content:space-around center;align-items:center;margin:0;padding:0;list-style-type:none;display:flex}header nav ul li,header nav ol li{display:inline-block}header nav a,header nav a:visited{border:var(--border-width)solid var(--border);border-radius:var(--standard-border-radius);color:var(--text);margin:0 .5rem 1rem;padding:.1rem 1rem;text-decoration:none;display:inline-block}header nav a:hover,header nav a.current,header nav a[aria-current=page],header nav a[aria-current=true]{border-color:var(--accent);color:var(--accent);cursor:pointer}@media only screen and (width<=720px){header nav a{border:none;padding:0;line-height:1;text-decoration:underline}}aside,details,pre,progress{background-color:var(--accent-bg);border:var(--border-width)solid var(--border);border-radius:var(--standard-border-radius);margin-bottom:1rem}aside{float:right;width:30%;margin-inline-start:15px;padding:0 15px;font-size:1rem}[dir=rtl] aside{float:left}@media only screen and (width<=720px){aside{float:none;width:100%;margin-inline-start:0}}article,fieldset,dialog{border:var(--border-width)solid var(--border);border-radius:var(--standard-border-radius);margin-bottom:1rem;padding:1rem}article h2:first-child,section h2:first-child,article h3:first-child,section h3:first-child{margin-top:1rem}section{border-top:var(--border-width)solid var(--border);border-bottom:var(--border-width)solid var(--border);margin:3rem 0;padding:2rem 1rem}section+section,section:first-child{border-top:0;padding-top:0}section+section{margin-top:0}section:last-child{border-bottom:0;padding-bottom:0}details{padding:.7rem 1rem}summary{cursor:pointer;word-break:break-all;margin:-.7rem -1rem;padding:.7rem 1rem;font-weight:700}details[open]>summary+*{margin-top:0}details[open]>summary{margin-bottom:.5rem}details[open]>:last-child{margin-bottom:0}table{border-collapse:collapse;margin:1.5rem 0}figure>table{width:max-content;margin:0}td,th{border:var(--border-width)solid var(--border);text-align:start;padding:.5rem}th{background-color:var(--accent-bg);font-weight:700}tr:nth-child(2n){background-color:var(--accent-bg)}table caption{margin-bottom:.5rem;font-weight:700}textarea,select,input,button,.button{font-size:inherit;border-radius:var(--standard-border-radius);box-shadow:none;max-width:100%;margin-bottom:.5rem;padding:.5em;font-family:inherit;display:inline-block}textarea,select,input{color:var(--text);background-color:var(--bg);border:var(--border-width)solid var(--border)}label{display:block}textarea:not([cols]){width:100%}select:not([multiple]){background-image:linear-gradient(45deg,transparent 49%,var(--text)51%),linear-gradient(135deg,var(--text)51%,transparent 49%);background-position:calc(100% - 15px),calc(100% - 10px);background-repeat:no-repeat;background-size:5px 5px,5px 5px;padding-inline-end:25px}[dir=rtl] select:not([multiple]){background-position:10px,15px}input[type=checkbox],input[type=radio]{vertical-align:middle;width:min-content;position:relative}input[type=checkbox]+label,input[type=radio]+label{display:inline-block}input[type=radio]{border-radius:100%}input[type=checkbox]:checked,input[type=radio]:checked{background-color:var(--accent)}input[type=checkbox]:checked:after{content:" ";border-right:solid var(--bg).08em;border-bottom:solid var(--bg).08em;background-color:#0000;border-radius:0;width:.2em;height:.4em;font-size:1.8em;position:absolute;top:.04em;left:.18em;transform:rotate(45deg)}input[type=radio]:checked:after{content:" ";background-color:var(--bg);border-radius:100%;width:.3em;height:.3em;font-size:1.8em;position:absolute;top:.125em;left:.125em}@media only screen and (width<=720px){textarea,select,input{width:100%}}input[type=color]{height:2.5rem;padding:.2rem}input[type=file]{border:0}hr{height:var(--border-width);background:var(--border);border:none;margin:1rem auto}mark{border-radius:var(--standard-border-radius);background-color:var(--marked);color:#000;padding:2px 5px}mark a{color:#0d47a1}img,video{border-radius:var(--standard-border-radius);max-width:100%;height:auto}figure{margin:0;display:block;overflow-x:auto}figure>img,figure>picture>img{margin-inline:auto;display:block}figcaption{text-align:center;color:var(--text-light);margin-block:1rem;font-size:.9rem;position:sticky;left:0}blockquote{border-inline-start:.35rem solid var(--accent);color:var(--text-light);margin-block:2rem;margin-inline:2rem 0;padding:.4rem .8rem;font-style:italic}cite{color:var(--text-light);font-size:.9rem;font-style:normal}dt{color:var(--text-light)}code,pre,pre span,kbd,samp{font-family:var(--mono-font);color:var(--code)}kbd{color:var(--preformatted);border:var(--border-width)solid var(--preformatted);border-bottom:3px solid var(--preformatted);border-radius:var(--standard-border-radius);padding:.1rem .4rem}pre{max-width:100%;color:var(--preformatted);padding:1rem 1.4rem;overflow:auto}pre code{color:var(--preformatted);background:0 0;margin:0;padding:0}progress{width:100%}progress:indeterminate{background-color:var(--accent-bg)}progress::-webkit-progress-bar{border-radius:var(--standard-border-radius);background-color:var(--accent-bg)}progress::-webkit-progress-value{border-radius:var(--standard-border-radius);background-color:var(--accent)}progress::-moz-progress-bar{border-radius:var(--standard-border-radius);background-color:var(--accent);transition-property:width;transition-duration:.3s}progress:indeterminate::-moz-progress-bar{background-color:var(--accent-bg)}dialog{background-color:var(--bg);max-width:40rem;margin:auto}dialog::backdrop{background-color:var(--bg);opacity:.8}@media only screen and (width<=720px){dialog{max-width:calc(100vw - 2rem)}}sup,sub{vertical-align:baseline;position:relative}sup{top:-.4em}sub{top:.3em}.notice{background:var(--accent-bg);border:var(--border-width)solid var(--border);border-radius:var(--standard-border-radius);margin:2rem 0;padding:1.5rem}@media print{@page{margin:1cm}body{display:block}body>header{background-color:unset}body>header nav,body>footer{display:none}article{border:none;padding:0}a[href^=http]:after{content:" <" attr(href)">"}abbr[title]:after{content:" (" attr(title)")"}a{text-decoration:none}p{widows:3;orphans:3}hr{border-top:var(--border-width)solid var(--border)}mark{border:var(--border-width)solid var(--border)}pre,table,figure,img,svg{break-inside:avoid}pre code{white-space:pre-wrap}}
.mdo-source-meta{margin-top:3rem;border:0;padding:1rem 0 1.5rem;font-size:.8rem;line-height:1.4;color:var(--text-light);text-align:center}
</style>
<style id="mdo-theme-toggle">
:root[data-theme="light"]{color-scheme:light;--bg:#fff;--accent-bg:#f5f7ff;--text:#212121;--text-light:#585858;--accent:#0d47a1;--accent-hover:#1266e2;--accent-text:var(--bg);--code:#d81b60;--preformatted:#444;--disabled:#efefef}
:root[data-theme="dark"]{color-scheme:dark;--bg:#212121;--accent-bg:#2b2b2b;--text:#dcdcdc;--text-light:#ababab;--accent:#ffb300;--accent-hover:#ffe099;--accent-text:var(--bg);--code:#f06292;--preformatted:#ccc;--disabled:#111}
:root[data-theme="dark"] img,:root[data-theme="dark"] video{opacity:.8}
#theme-toggle{position:fixed;top:.75rem;right:.75rem;z-index:1000;padding:.25rem .6rem;font-size:1rem;line-height:1;cursor:pointer;border-radius:var(--standard-border-radius);border:var(--border-width) solid var(--border);background:var(--accent-bg);color:var(--text)}
@media (max-width:55rem){body{padding-top:2.75rem}}
@media print{#theme-toggle{display:none}}
</style>
<script>
(function(){
var read=function(){try{return localStorage.getItem('theme')}catch(e){return null}};
var apply=function(t){document.documentElement.dataset.theme=t;};
var mq=matchMedia('(prefers-color-scheme: dark)');
var saved=read();
var manual=saved!==null;
apply(saved||(mq.matches?'dark':'light'));
document.addEventListener('DOMContentLoaded',function(){
var b=document.createElement('button');
b.id='theme-toggle';b.type='button';
var sync=function(){
var dark=document.documentElement.dataset.theme==='dark';
b.textContent=dark?'\u2600':'\u263E';
var label=dark?'Switch to light theme':'Switch to dark theme';
b.title=label;
b.setAttribute('aria-label',label);
};
b.onclick=function(){
var next=document.documentElement.dataset.theme==='dark'?'light':'dark';
apply(next);
manual=true;
try{localStorage.setItem('theme',next)}catch(e){}
sync();
};
if(mq.addEventListener){
mq.addEventListener('change',function(e){
if(!manual){apply(e.matches?'dark':'light');sync();}
});
}
document.body.appendChild(b);
sync();
});
})();
</script>
<style id="mdo-default-typography">
/* mdo's default typography layer.
This is embedded after the vendored simple.css base and before any --css file. */
body {
font-size: 1rem;
}
h1 {
font-size: 2.4rem;
}
h2 {
font-size: 2rem;
}
h3 {
font-size: 1.4rem;
}
</style>
</head>
<body>
<main>
<h1>Open Markdown as HTML</h1>
<p><code>mdo</code> is a small, fast, self-contained command-line tool that turns a
Markdown file into a styled, standalone HTML5 page — because Markdown is
great for writing and diffing, but calmer to <em>read</em> in a browser. Pages
include embedded <a href="https://simplecss.org/" rel="noopener noreferrer">simple.css</a> styling and automatic
light/dark mode with a manual toggle, and mdo makes no network calls at
runtime. With the optional file-manager integration, opening a <code>.md</code> file as
rendered HTML is as fast as opening it in a text editor. Linux, macOS, and
Windows.</p>
<p>Project site: <a href="https://maphew.github.io/mdo/" rel="noopener noreferrer">https://maphew.github.io/mdo/</a> ·
Public metrics: <a href="https://maphew.github.io/mdo/metrics/" rel="noopener noreferrer">https://maphew.github.io/mdo/metrics/</a></p>
<h2>Install</h2>
<p>Linux and macOS:</p>
<pre><code class="language-bash">curl -fsSL https://maphew.github.io/mdo/install.sh | sh
</code></pre>
<p>Windows PowerShell:</p>
<pre><code class="language-powershell">irm https://maphew.github.io/mdo/install.ps1 | iex
</code></pre>
<p>The hosted installers fetch the latest
<a href="https://github.com/maphew/mdo/releases" rel="noopener noreferrer">GitHub Release</a>, verify it against
<code>SHA256SUMS</code>, and install into a user-local bin directory
(<code>$HOME/.local/bin</code>, or <code>%LOCALAPPDATA%\mdo\bin</code> on Windows; set
<code>MDO_INSTALL_DIR</code> to change). Manual archives are on the Releases page.</p>
<p>Rust users can build from source instead with <code>cargo install mdo-cli</code>
(needs a working Rust toolchain, including the MSVC linker on Windows), or
<code>git clone</code> + <code>cargo build --release</code>.</p>
<h3>Android preview</h3>
<p>The native Android app can open a Markdown document from the system picker or
handle it from a Files app, then renders it locally through mdo's shared Rust
engine. Download the signed ARM64 APK from the
<a href="https://github.com/maphew/mdo/releases/latest/download/mdo-android-arm64.apk" rel="noopener noreferrer">latest GitHub Release</a>.
Android installation, build, and usage details are in
<a href="android/README.md" rel="noopener noreferrer"><code>android/README.md</code></a>.</p>
<h2>Use</h2>
<pre><code class="language-bash">mdo FILE.md # convert once; writes FILE.html next to the source
mdo --open FILE.md # render to a temp page and open it in your browser
mdo --watch FILE.md # re-render automatically on every save
</code></pre>
<p><code>mdo --open</code> never leaves <code>.html</code> files beside your Markdown (unless you pass
<code>--output</code> to redirect it there yourself) — output goes to a stable per-file
temp path, and relative images and links still resolve.
Running <code>mdo</code> with no arguments prints a short landing page; <code>mdo --help</code>
shows the full reference.</p>
<p>Full CLI reference, output details, and examples: <a href="docs/usage.md" rel="noopener noreferrer">docs/usage.md</a>.</p>
<h2>File-manager integration</h2>
<p>The core convenience: right-click or double-click a <code>.md</code> file and read it as
HTML immediately, with no generated files left beside the source.</p>
<pre><code class="language-bash">mdo --setup # guided first-run setup (offers the install)
mdo --install-file-manager # add "Open as HTML" for Markdown files
mdo --uninstall-file-manager # remove everything the installer added
</code></pre>
<ul>
<li><strong>Windows</strong> — right-click a <code>.md</code> file → <strong>Open as HTML</strong> (per-user
registry entries only; no admin rights). Release ZIPs include a
double-clickable <code>mdo-setup.exe</code> for guided setup.</li>
<li><strong>Linux</strong> — <strong>Open With → Open as HTML</strong> in XDG file managers; add
<code>--set-default</code> to make it the default Markdown handler. Release archives
include an <code>mdo-setup</code> launcher.</li>
<li><strong>macOS</strong> — a short Automator Quick Action recipe (no installer yet).</li>
</ul>
<p>Everything is per-user, quiet, and reversible. Platform details:
<a href="docs/file-manager-integration.md" rel="noopener noreferrer">docs/file-manager-integration.md</a>.</p>
<h2>Security</h2>
<p>Raw HTML inside Markdown is <strong>sanitized by default</strong> (scripts and
event-handler attributes removed); <code>--unsafe-html</code> disables that for trusted
input only. mdo makes no network calls at runtime, and the file-manager
integration is strictly per-user. Details and reporting:
<a href="SECURITY.md" rel="noopener noreferrer">SECURITY.md</a>.</p>
<h2>Project status — feedback wanted</h2>
<p>mdo is young and honest about it: v0.5 is released, v0.6 is in progress. It
does its core job — double-click a <code>.md</code> file, get a rendered page — every
day on the author's Windows and Linux machines. macOS binaries are built and
released but are the least exercised, and the Finder integration is still a
manual recipe.</p>
<p>What we don't know yet is whether mdo is useful to anyone who isn't the
author. That's the question this phase of the project exists to answer, and
you can help:</p>
<ul>
<li><strong>Tried it?</strong> <a href="https://github.com/maphew/mdo/issues/new?template=experience_report.yml" rel="noopener noreferrer">Tell us how it went</a>
— "worked, keeping it" and "gave up during setup" are equally valuable.</li>
<li><strong>Something broke?</strong> <a href="https://github.com/maphew/mdo/issues/new?template=bug_report.yml" rel="noopener noreferrer">File a bug</a>.</li>
<li><strong>Just want to talk?</strong> <a href="https://github.com/maphew/mdo/discussions" rel="noopener noreferrer">Discussions</a> are open.</li>
</ul>
<p>Critique is welcome at full strength, including "this shouldn't exist because
X already does it better." See <a href="CONTRIBUTING.md" rel="noopener noreferrer">CONTRIBUTING.md</a> for more,
including a candid note on how this project is built.</p>
<h2>Documentation</h2>
<ul>
<li><a href="docs/usage.md" rel="noopener noreferrer">Usage and CLI reference</a></li>
<li><a href="docs/file-manager-integration.md" rel="noopener noreferrer">File-manager integration</a></li>
<li><a href="docs/custom-css.md" rel="noopener noreferrer">Custom CSS</a></li>
<li><a href="docs/maintaining.md" rel="noopener noreferrer">Maintaining</a> — releases, packaging, docs site, metrics</li>
<li><a href="CHANGELOG.md" rel="noopener noreferrer">Changelog</a></li>
<li><a href="docs/adr/" rel="noopener noreferrer">Architecture decision records</a></li>
</ul>
<h2>Credits and license</h2>
<p>This project is a grateful fork of Hafiz Ali Raza's original
Markdown-to-HTML CLI. Hafiz remains credited as an author, and this fork
keeps that lineage explicit so future improvements can be offered back
upstream. The bundled <a href="https://simplecss.org/" rel="noopener noreferrer">simple.css</a> is © 2020
<a href="https://kevquirk.com/" rel="noopener noreferrer">Kev Quirk</a>, MIT License — see
<a href="assets/simple.css.LICENSE" rel="noopener noreferrer"><code>assets/simple.css.LICENSE</code></a>.</p>
<p>Dual-licensed under either the <a href="LICENSE-MIT" rel="noopener noreferrer">MIT License</a> or the
<a href="LICENSE-APACHE" rel="noopener noreferrer">Apache License, Version 2.0</a>, at your option, matching the
upstream project.</p>
</main>
<footer class="mdo-source-meta">Source modified: <time datetime="2026-07-22T23:18:50Z">July 22, 2026, 11:18 PM UTC</time></footer>
<script>
(function(){var t=document.querySelector('.mdo-source-meta time');if(!t)return;var d=new Date(t.getAttribute('datetime'));if(isNaN(d))return;try{t.textContent=d.toLocaleString(undefined,{year:'numeric',month:'long',day:'numeric',hour:'numeric',minute:'2-digit'});}catch(e){}})();
</script>
</body>
</html>