参考 JavaScript get clipboard data on paste event (Cross browser)和Insert text into textarea at cursor position (Javascript)实现了基本的功能,可以像简书那样将粘贴的链接自动转换为Markdown格式。在Chrome 51测试。未做其他的兼容性测试。
效果如下:
代码结构
源码
见 https://github.com/letiantian/paste-as-markdown
这里贴下源码:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Paste as Markdown</title>
<link href="//cdn.bootcss.com/bootstrap/3.1.0/css/bootstrap.min.css" rel="stylesheet">
<style type="text/css">
textarea {
width: 100%;
height: 200px;
}
</style>
</head>
<body>
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
<h1>复制粘贴为Markdown格式</h1>
<hr/>
<p>这是一段文本</p>
<p><a href="/bundle.js">Link One</a></p>
<p><a href="https://github.com/letiantian">Link Two</a></p>
<p><img src="./art.png" /></p>
<hr/>
<p>
<button id="addText" class="btn-primary">在光标位置添加文本</button>
</p>
<textarea id="content">Paste</textarea>
</div>
<div class="col-md-3"></div>
</div>
<script src="//cdn.bootcss.com/jquery/2.2.2/jquery.min.js"></script>
<script src="//cdn.bootcss.com/bootstrap/3.1.0/js/bootstrap.min.js"></script>
<script src="./bundle.js"></script>
</body>
</html>
bundle.js
var editableTextArea = document.getElementById('content');
function handlepaste (e) {
var types, pastedData, savedContent;
// Browsers that support the 'text/html' type in the Clipboard API (Chrome, Firefox 22+)
if (e && e.clipboardData && e.clipboardData.types && e.clipboardData.getData) {
console.log(e.clipboardData);
// Check for 'text/html' in types list. See abligh's answer below for deatils on
// why the DOMStringList bit is needed. We cannot fall back to 'text/plain' as
// Safari/Edge don't advertise HTML data even if it is available
types = e.clipboardData.types;
if (((types instanceof DOMStringList) && types.contains("text/html")) || (types.indexOf && types.indexOf('text/html') !== -1)) {
// Extract data and pass it to callback
pastedData = e.clipboardData.getData('text/html');
console.log(pastedData);
typeInTextarea($('#content'), processHtmlData(pastedData));
// Stop the data from actually being pasted
e.stopPropagation();
e.preventDefault();
return false;
}
}
}
function typeInTextarea(el, newText) {
var start = el.prop("selectionStart")
var end = el.prop("selectionEnd")
var text = el.val()
var before = text.substring(0, start)
var after = text.substring(end, text.length)
el.val(before + newText + after)
el[0].selectionStart = el[0].selectionEnd = start + newText.length
el.focus()
return false
}
function processHtmlData(data) {
data = '<div>' + data + '</div>'; // let find() run
var dataDom = $(data);
dataDom.filter('script').remove();
dataDom.filter('style').remove();
// process <a></a>
dataDom.find('a').each(function(idx, item) {
console.log('find a link');
var url = $(item).attr("href");
var content = $(item).text();
$(this).text('['+content+'](' + url + ')');
});
// process <img/>
dataDom.find('img').each(function(idx, item) {
console.log('find an img');
var url = $(item).attr("src");
var content = '';
$(this).after('<span>!['+content+'](' + url + ')</span>');
});
console.log('after process img: ' + dataDom.html());
// process p,h1,h2,...
['p', 'h1', 'h2', 'h3', 'h4'].forEach(function(tag, idx){
dataDom.find(tag).each(function(index, item) {
var content = $(item).html().trim();
if (content.length > 0)
$(this).html(content + ' '); // add new line
});
});
return dataDom.text().trim();
}
// Modern browsers. Note: 3rd argument is required for Firefox <= 6
editableTextArea.addEventListener('paste', handlepaste, false);
// add text button
function processButtonClick() {
typeInTextarea($('#content'), 'Hello, ~');
}
document.getElementById('addText').addEventListener('click', processButtonClick, false);