zhanyaha / Copy Markdown from HTML

// ==UserScript==
// @name         Copy Markdown from HTML
// @namespace    http://tampermonkey.net/
// @version      0.5
// @description  按ctrl + z将选中内容转换为Markdown格式并加入剪贴板
// @description:en Press ctrl + z to convert the selected HTML to Markdown format and add to the clipboard
// @copyright 2019, zhanyaha
// @license MIT
// @author       zhanyaha
// @match        *://*/*
// @require      https://unpkg.com/turndown/dist/turndown.js
// @require      https://unpkg.com/turndown-plugin-gfm/dist/turndown-plugin-gfm.js
// @grant        GM_setClipboard
// ==/UserScript==

(function() {
    'use strict';
    function commonParentNode(oNode1, oNode2) {
        if(oNode1===oNode2){
            return oNode1.parentNode;
        }
        for(;;oNode1=oNode1.parentNode) {
            if(oNode1.contains(oNode2)){
                return oNode1;
            }
        }
    }

    document.addEventListener("keydown", function(e) {
        if(e.ctrlKey && e.keyCode == 90 ){
            var sel=document.getSelection();
            var relative_pos=sel.anchorNode.compareDocumentPosition(sel.focusNode);
            var content = commonParentNode(sel.anchorNode,sel.focusNode);
            let fragment = document.createDocumentFragment();
            if(content.children.length===0){
                fragment.appendChild(content.cloneNode(true));
            }
            for(let item of content.children){
                var p1 = item.compareDocumentPosition(sel.anchorNode);
                var p2 = item.compareDocumentPosition(sel.focusNode);
                if(relative_pos!==2){
                    if(p1===4 || p2===2){
                        continue;
                    }
                }else{
                    if(p1===2 || p2===4){
                        continue;
                    }
                }
                fragment.appendChild(item.cloneNode(true));
            }
            var imgDatas = '';
            var count = 0;
            function getMarkdown(container){
                var turndownService = new TurndownService({ codeBlockStyle: 'fenced' });
                var gfm = turndownPluginGfm.gfm;
                turndownService.use(gfm)
                turndownService.keep(['pre']);
                turndownService.remove('script')
                turndownService.addRule('image', {
                    filter: 'img',
                    replacement: function (content, node) {
                        return '!['+ node.alt+ '][' + node.id + ']';
                    }
                })
                var markdown = turndownService.turndown(container);
                markdown = '> From ['+location.href+']('+location.href+')\n\n'+markdown+imgDatas;
                GM_setClipboard(markdown);
            }
            var imgs = fragment.querySelectorAll('img');
            if(imgs.length){
                imgs.forEach(function(item,index){
                    GM_xmlhttpRequest({
                        method: 'GET',
                        url:item.src,
                        responseType:'blob',
                        headers: {
                            referer:location.href
                        },
                        onload: function(res) {
                            let reader = new FileReader();
                            reader.onloadend = (function (i){
                                return function(){
                                    imgDatas += '\n\n[img'+i+']:'+reader.result;
                                    count++;
                                    if(count ===  imgs.length){
                                        getMarkdown(fragment);
                                    }
                                };
                            })(index);
                            let blob = res.response.slice(0,res.response.size,/(?:content-type:\s*)(.*)/g.exec(res.responseHeaders)[1]);
                            reader.readAsDataURL(blob);
                            item.id = 'img'+index;
                        },
                        onerror: function(e) {
                            console.error(e);
                        }
                    });
                });
            }else{
                getMarkdown(fragment);
            }
        }
    })
})();