什麼是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