什么是markdown
Markdown
是一种轻量级标记语言,创始人为约翰·格鲁伯(John Gruber)。 它允许人们使用易读易写的纯文本格式编写文档,然后转换成有效的 XHTML(或者HTML)文档。这种语言吸收了很多在电子邮件中已有的纯文本标记的特性。
由于 Markdown
的轻量化、易读易写特性,并且对于图片,图表、数学式都有支持,许多网站都广泛使用 Markdown
来撰写帮助文档或是用于论坛上发表消息。 如 GitHub
、Reddit
、Diaspora
、Stack Exchange
、OpenStreetMap
、SourceForge
、简书等,甚至还能被使用来撰写电子书。现在我们所看的 segmentfault
的编辑器也是支持markdown语法的!
上代码
</!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<script src="https://cdn.staticfile.org/jquery/3.6.1/jquery.min.js"></script>
<style>
*{
padding: 0;
margin: 0;
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;
}
#app{
width: 1610px;
height: 800px;
margin: 30px auto 0;
padding: 10px 10px;
background: #eee;
}
#app .md-editor{
width: 800px;
height: 800px;
float: left;
}
#app .md-content{
width: 100%;
height: 800px;
outline: none;
resize: none;
padding: 10px 10px;
font-size: 16px;
border: none;
background: #fff;
color: #666;
}
#app .md-html{
width: 780px;
height: 780px;
float: right;
background: #fff;
padding: 10px 10px;
line-height: 20px;
}
#app .md-html .placeholder{
font-size: 16px;
color: #666;
}
#app code{
color: #666;
padding: 3px 5px;
background: #f1f1f1;
border-radius: 2px;
font-size: 12px;
}
#app pre{
/*width: 100%;*/
/*display: block;*/
color: #666;
padding: 10px 10px;
background: #f1f1f1;
border-radius: 5px;
font-size: 14px;
}
h1, h2, h3, h4, h5, h6{
font-weight: 600;
line-height: 1.25;
margin-bottom: 0;
}
h1, h2{
border-bottom: 1px solid #eaecef;
padding-bottom: 12px;
}
</style>
</head>
<body>
<h2 style="text-align: center;margin-top: 50px;">JavaScript实现一个简单的Markdown语法解析器</h2>
<div id="app">
<div class="md-editor">
<form>
<textarea name="md-content" class="md-content" placeholder="在这里使用markdown语法编写"></textarea>
</form>
</div>
<div class="md-html"><span class="placeholder">这里会实时显示markdown语法的解析结果</span></div>
</div>
<script type="text/javascript">
// 解析markdown语法为html
function markdownToHTML(markdown) {
// 将Markdown文本分成多行
const lines = markdown.split('\n');
// 用于保存解析后的HTML代码
let result = '';
// 遍历每一行Markdown文本
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
// 处理标题
if (line.startsWith('#')) {
const level = line.match(/^#+/)[0].length;
const title = line.substring(level).trim();
result += `<h${level}>${title}</h${level}>`;
}
// 处理无序列表
else if (line.startsWith('* ')) {
const text = line.substring(2).trim();
result += `<li>${text}</li>`;
}
// 处理有序列表
else if (/^\d+\.\s/.test(line)) {
const text = line.substring(line.indexOf('.') + 1).trim();
result += `<li>${text}</li>`;
}
// 处理加粗
else if (line.startsWith('**')) {
result += line.replace(/\*\*(.*)\*\*/gm, '<strong>$1</strong>');
}
else if (line.startsWith('__')) {
result += line.replace(/__(.*)__/gm, '<strong>$1</strong>');
}
// 处理斜体
else if (line.startsWith('*')) {
result += line.replace(/\*(.*)\*/gm, '<em>$1</em>');
}
else if (line.startsWith('_')) {
result += line.replace(/_(.*)_/gm, '<em>$1</em>');
}
// 处理删除线
else if (line.startsWith('~~')) {
result += line.replace(/~~(.*)~~/gm, '<del>$1</del>');
}
// 处理超链接
else if (line.startsWith('[')) {
result += line.replace(/\[(.*?)\]\((.*?)\)/gm, '<a href="$2">$1</a>');
}
// 处理图片
else if (line.startsWith('![')) {
result += line.replace(/!\[(.*?)\]\((.*?)\)/gm, '<img src="$2" alt="$1" width="200" />');
}
// 处理行内代码
else if (line.startsWith('`')) {
result += escapeHtml(line).replace(/`(.*?)`/gm, '<code>$1</code>');
}
// 处理段落
else {
if(line.length == 0){
result += `<br/>`;
}else{
result += `<p>${line}</p>`;
}
}
}
// 包装HTML代码
result = `<div>${result}</div>`;
return result;
}
// html转义
function escapeHtml(str) {
return str.replace(/[&<>"']/g, function(match) {
switch(match) {
case '&':
return '&';
case '<':
return '<';
case '>':
return '>';
case '"':
return '"';
case '\'':
return ''';
}
});
}
// 实时解析markdown语法
$("#app .md-editor .md-content").bind("input propertychange",function(event){
let md_content = $('#app .md-editor .md-content').val();
if(md_content){
$('#app .md-html').html(markdownToHTML(md_content));
}else{
$('#app .md-html').html('<span class="placeholder">这里会实时显示markdown语法的解析结果</span>');
}
});
</script>
</body>
</html>
实现原理
实现起来非常简单,就是通过正则替换预定的字符来实现HTML的输出。
demo
作者
TANKING
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。