Skip to content

Commit 782395b

Browse files
authored
1 parent baebe57 commit 782395b

File tree

1 file changed

+246
-0
lines changed

1 file changed

+246
-0
lines changed

render-markdown.html

+246
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
<html>
2+
<head>
3+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
4+
<title>Render Markdown</title>
5+
<script defer data-domain="tools.simonwillison.net" src="https://plausible.io/js/plausible.js"></script>
6+
<style>
7+
body {
8+
padding: 1em;
9+
margin: 0
10+
}
11+
#preview {
12+
padding: 0.5em;
13+
border: 1px dotted black;
14+
}
15+
16+
button {
17+
font-size: 1.4em;
18+
}
19+
20+
/*!
21+
* GitHub Light v0.5.0
22+
* Copyright (c) 2012 - 2017 GitHub, Inc.
23+
* Licensed under MIT (https://github.com/primer/github-syntax-theme-generator/blob/master/LICENSE)
24+
*/
25+
26+
.pl-c /* comment, punctuation.definition.comment, string.comment */ {
27+
color: #6a737d;
28+
}
29+
30+
.pl-c1 /* constant, entity.name.constant, variable.other.constant, variable.language, support, meta.property-name, support.constant, support.variable, meta.module-reference, markup.raw, meta.diff.header, meta.output */,
31+
.pl-s .pl-v /* string variable */ {
32+
color: #005cc5;
33+
}
34+
35+
.pl-e /* entity */,
36+
.pl-en /* entity.name */ {
37+
color: #6f42c1;
38+
}
39+
40+
.pl-smi /* variable.parameter.function, storage.modifier.package, storage.modifier.import, storage.type.java, variable.other */,
41+
.pl-s .pl-s1 /* string source */ {
42+
color: #24292e;
43+
}
44+
45+
.pl-ent /* entity.name.tag, markup.quote */ {
46+
color: #22863a;
47+
}
48+
49+
.pl-k /* keyword, storage, storage.type */ {
50+
color: #d73a49;
51+
}
52+
53+
.pl-s /* string */,
54+
.pl-pds /* punctuation.definition.string, source.regexp, string.regexp.character-class */,
55+
.pl-s .pl-pse .pl-s1 /* string punctuation.section.embedded source */,
56+
.pl-sr /* string.regexp */,
57+
.pl-sr .pl-cce /* string.regexp constant.character.escape */,
58+
.pl-sr .pl-sre /* string.regexp source.ruby.embedded */,
59+
.pl-sr .pl-sra /* string.regexp string.regexp.arbitrary-repitition */ {
60+
color: #032f62;
61+
}
62+
63+
.pl-v /* variable */,
64+
.pl-smw /* sublimelinter.mark.warning */ {
65+
color: #e36209;
66+
}
67+
68+
.pl-bu /* invalid.broken, invalid.deprecated, invalid.unimplemented, message.error, brackethighlighter.unmatched, sublimelinter.mark.error */ {
69+
color: #b31d28;
70+
}
71+
72+
.pl-ii /* invalid.illegal */ {
73+
color: #fafbfc;
74+
background-color: #b31d28;
75+
}
76+
77+
.pl-c2 /* carriage-return */ {
78+
color: #fafbfc;
79+
background-color: #d73a49;
80+
}
81+
82+
.pl-c2::before /* carriage-return */ {
83+
content: "^M";
84+
}
85+
86+
.pl-sr .pl-cce /* string.regexp constant.character.escape */ {
87+
font-weight: bold;
88+
color: #22863a;
89+
}
90+
91+
.pl-ml /* markup.list */ {
92+
color: #735c0f;
93+
}
94+
95+
.pl-mh /* markup.heading */,
96+
.pl-mh .pl-en /* markup.heading entity.name */,
97+
.pl-ms /* meta.separator */ {
98+
font-weight: bold;
99+
color: #005cc5;
100+
}
101+
102+
.pl-mi /* markup.italic */ {
103+
font-style: italic;
104+
color: #24292e;
105+
}
106+
107+
.pl-mb /* markup.bold */ {
108+
font-weight: bold;
109+
color: #24292e;
110+
}
111+
112+
.pl-md /* markup.deleted, meta.diff.header.from-file, punctuation.definition.deleted */ {
113+
color: #b31d28;
114+
background-color: #ffeef0;
115+
}
116+
117+
.pl-mi1 /* markup.inserted, meta.diff.header.to-file, punctuation.definition.inserted */ {
118+
color: #22863a;
119+
background-color: #f0fff4;
120+
}
121+
122+
.pl-mc /* markup.changed, punctuation.definition.changed */ {
123+
color: #e36209;
124+
background-color: #ffebda;
125+
}
126+
127+
.pl-mi2 /* markup.ignored, markup.untracked */ {
128+
color: #f6f8fa;
129+
background-color: #005cc5;
130+
}
131+
132+
.pl-mdr /* meta.diff.range */ {
133+
font-weight: bold;
134+
color: #6f42c1;
135+
}
136+
137+
.pl-ba /* brackethighlighter.tag, brackethighlighter.curly, brackethighlighter.round, brackethighlighter.square, brackethighlighter.angle, brackethighlighter.quote */ {
138+
color: #586069;
139+
}
140+
141+
.pl-sg /* sublimelinter.gutter-mark */ {
142+
color: #959da5;
143+
}
144+
145+
.pl-corl /* constant.other.reference.link, string.other.link */ {
146+
text-decoration: underline;
147+
color: #032f62;
148+
}
149+
</style>
150+
</head>
151+
<body>
152+
<h1>Render Markdown</h1>
153+
<p>Using GitHub's API, see <a href="/til/til/markdown_github-markdown-api.md">Rendering Markdown with the GitHub Markdown API</a></p>
154+
<p><textarea id="input" style="width: 80%; height: 10em"></textarea></p>
155+
<p>
156+
<button>Render</button>
157+
<label><input type="checkbox" id="strip_hidden" checked> Strip hidden and cleanup HTML</label>
158+
<label><input type="checkbox" id="gfm_mode"> Use GitHub Flavored Markdown (GFM)</label>
159+
</p>
160+
<p><textarea id="output" style="width: 80%; height: 10em"></textarea></p>
161+
<div id="preview"></div>
162+
<script>
163+
const button = document.getElementsByTagName('button')[0];
164+
const strip_hidden = document.getElementById('strip_hidden');
165+
const input = document.getElementById('input');
166+
const output = document.getElementById('output');
167+
const preview = document.getElementById('preview');
168+
button.addEventListener('click', async function() {
169+
const rendered = await render(input.value);
170+
output.value = rendered;
171+
preview.innerHTML = rendered;
172+
if (strip_hidden.checked) {
173+
Array.from(
174+
preview.querySelectorAll('[aria-hidden]')
175+
).forEach(el => el.parentNode.removeChild(el));
176+
Array.from(
177+
preview.querySelectorAll('[rel="nofollow"]')
178+
).forEach(el => el.removeAttribute('rel'));
179+
// <div class="highlight highlight-source-python">
180+
Array.from(
181+
preview.querySelectorAll('div.highlight-source-python')
182+
).forEach(el => el.replaceWith(el.firstChild));
183+
/* Remove <a href="https://camo.githubusercontent.com"... wrapper
184+
links around images, and replace src= with data-canonical-src= */
185+
Array.from(
186+
preview.querySelectorAll(
187+
'a[href^="https://camo.githubusercontent.com"]'
188+
)
189+
).forEach(el => el.replaceWith(el.firstChild));
190+
Array.from(
191+
preview.querySelectorAll(
192+
'img[data-canonical-src]'
193+
)
194+
).forEach(
195+
el => {
196+
el.setAttribute('src', el.getAttribute('data-canonical-src'));
197+
el.removeAttribute('data-canonical-src');
198+
}
199+
);
200+
// Remove <a class="heading-link"> links, replace with their content
201+
Array.from(
202+
preview.querySelectorAll('a.heading-link')
203+
).forEach(el => el.replaceWith(el.firstChild));
204+
// Output it to the textarea
205+
output.value = preview.innerHTML.replace(
206+
/<h([1-6])>\n/g, '<h$1>'
207+
).replace(
208+
/<br>/g, '<br />'
209+
).replace(
210+
/<img ([^>].+?)>/g, '<img $1 />'
211+
);
212+
}
213+
// And prepend the menu as well
214+
const menu = '<ul>\n' + (
215+
Array.from(
216+
document.querySelectorAll('h2[id],h3[id],h4[id],h5[id],h6[id]')
217+
).map(el => ` <li><a href="#${el.id}">${el.innerText}</a></li>`).join('\n')
218+
) + '\n</ul>';
219+
output.value = menu + '\n\n' + output.value;
220+
preview.innerHTML = menu + '\n\n' + preview.innerHTML;
221+
});
222+
223+
async function render(markdown) {
224+
const mode = document.getElementById('gfm_mode').checked ? 'gfm' : 'markdown';
225+
return (await fetch('https://api.github.com/markdown', {
226+
method: 'POST',
227+
headers: {
228+
'Content-Type': 'application/json'
229+
},
230+
body: JSON.stringify({'mode': mode, 'text': markdown})
231+
})).text();
232+
}
233+
234+
/* Populate textarea from localStorage */
235+
if (!input.value && localStorage.getItem('saved')) {
236+
input.value = localStorage.getItem('saved');
237+
button.click();
238+
}
239+
input.addEventListener('input', () => {
240+
localStorage.setItem('saved', input.value);
241+
});
242+
243+
</script>
244+
245+
</body>
246+
</html>

0 commit comments

Comments
 (0)