高颜值markdown解析器:粘贴复制代码即可用(不用编译打包)

演示地址: https://lovecodeyou.github.io/web-utils-convert/utils/markdownShow/index.html
在这里插入图片描述

概述

  1. 支持代码高亮、复制
  2. 支持Github表情包,支持的表情包请参考此链接
  3. 支持mermaid美人鱼语法渲染
  4. 支持[toc]导航栏生成
  5. 支持侧边导航栏

核心代码

仓库代码位置

自行拉取,觉得好用还行顺便点个星星:https://gitee.com/changenen/web-utils-convert/tree/master/utils/markdownShow

Github:自行拉取,觉得好用还行顺便点个星星:https://github.com/lovecodeyou/web-utils-convert/tree/master/utils/markdownShow

在这里插入图片描述

markdownUtils.js


/**
 * 字符串是否不为空
 * @param content 字符串内容
 */
function strIsNotEmpty(content) {
    let result = content && content.length > 0;
    if( (typeof result) === 'string' ) {
        return result.length > 0;
    }else {
        return result ? true : false ;
    }
}

/**
 * 字符串是否为空
 * @param content 字符串内容
 */
function strIsEmpty(content) {
    return !strIsNotEmpty(content);
}

/**
 * 日志打印=由前端开关进行控制
 * @param logContents
 */
function log(...logContents) {
    // if (getGlobalLogSwitch()) {
    if (true) {
        console.log(...logContents);
    }
}


/**
 * markdown-it配置初始化
 */
let mdToHtmlGenerator2 = null;
function mdToHtml2ConfigInit() {
    //初始化配置信息
    if(!mdToHtmlGenerator2) {
        //流程图mermaid初始化配置
        mermaid.initialize({startOnLoad:true, theme: 'forest'});

        //markdown-it配置初始化
        mdToHtmlGenerator2 = new markdownit({
            html: true,
            linkify: true,
            typographer: true,
            breaks: true,  //开启自动换行符
            highlight: function (str, lang) {
                if (lang && hljs.getLanguage(lang)) {
                    try {
                        return '<pre class="hljs"><code>' +
                            hljs.highlight(str, {language: lang, ignoreIllegals: true}).value +
                            '</code></pre>';
                    } catch (__) {
                    }
                }
                return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>';
            },

        })
            .use(markdownItAnchor, {permalink: true, permalinkBefore: true, permalinkSymbol: '§'})
            .use(markdownItTocDoneRight)
            .use(markdownItTextualUml)
            .use(markdownItCodeCopy)
            .use(markdownitEmoji);
    }
}


/**
 * md转HTML之后样式修正添加侧边导航栏、以及修改侧边导航栏样式
 * @param mdContentHtml
 * @returns {*|jQuery}
 */
function mdContentHtml2AddSlideNav(mdContentHtml) {

    let articleSlideNavJq = $(mdContentHtml)
        .find(".table-of-contents")
        .clone(true)
        .addClass("article-slide-nav")
        .css({
            "position": "fixed",
            "white-space": "nowrap",
            "text-overflow": "ellipsis",
            "width": "14%",
            "right": "0",
            "top": "0",
            "margin-top": "var(--articleDetailPage-margintop)",
            "margin-right": "var(--articleDetailPage-marginright)",
            "overflow-x": "hidden",
            "padding": "0.5rem",
            "box-shadow": "0px 0px 12px rgba(0, 0, 0, 0.12)",
            "line-height": "var(--default-a-lineheight)",
        })
        .prepend("<p class='article-slide-nav-title'>目录</p>")
        .find(".article-slide-nav-title")
        .css({
            "border-bottom": "1px solid #e4e6eb",
            "margin":"0px",
            "line-height":"3rem",
            "font-weight":"500",
        })
        .end()
        .find("li")
        .css({
            "overflow": "hidden",
        })
        .end();

    articleSlideNavJq.find("ol").css({
        "padding-inline-start": "1.2rem",
    })

    articleSlideNavJq.find("ol:first").css({
        "padding-inline-start": "0rem",
    })

    return $(mdContentHtml)
        .append(articleSlideNavJq)
        .prop("outerHTML")

}


/**
 * md转HTML之后样式修正
 * @param mdContentHtml
 * @returns {*|jQuery}
 */
function mdContentHtml2StyleCorrection(mdContentHtml) {

    //表格样式修正
    //页面未渲染并不能获取到高度
    // let tdHeight = $(mdContentHtml).find("table th").css("height")
    let mdContentHtmlJq = $(mdContentHtml)
        .find("td:empty")
        .css({height: '2rem'})
        .end()
        .find("table")
        .css({
            'margin-top': '4rem',
            'border-collapse': 'collapse'
        })
        .end()
        .find("table th")
        .css({
            'font-weight': 'bold',
            'background': '#7B8184',
            'color': 'white',
            'border': '1px solid #EAEAEA'
        })
        .end()
        .find("table td")
        .css({
            'border': '1px solid #EAEAEA'
        })
        .end()

    //文章内的导航栏样式修正
    mdContentHtmlJq = mdContentHtmlJq.find(".table-of-contents:not(.article-slide-nav)")
        .css({"margin-bottom":"5rem"})
        .find("a")
        .css({
            "text-decoration": "underline",
            "color": "var(--default-a-clicked-color)"
        })
        .end()
        .end();

    //图片样式修正
    mdContentHtmlJq = mdContentHtmlJq.find("img")
        .css({"width":"80%"})
        .end();

    //代码样式修正
    mdContentHtmlJq = mdContentHtmlJq.find("pre")
        .css({
            "font-family":"Menlo, Monaco, Consolas, 'Courier New', monospace",
            "line-height":"1.5rem",
            "border-radius":"1%",
            "padding":"1rem",
            "padding-top":"2rem",
            "overflow-x":"scroll",
            "font-weight":"bold",
        })
        .end();

    //引用快样式
    mdContentHtmlJq = mdContentHtmlJq.find("blockquote")
        .css({
            "display":"block",
            "padding":"1rem",
            "border-left":"0.5rem solid #dddfe4",
            "background":"#eef0f4",
            "overflow":"auto",
            "word-break":"break-word",
        })
        .end();


    //删除mermaid语法内的复制按钮
    mdContentHtmlJq = mdContentHtmlJq.find(".mermaid")
        .siblings(".markdown-it-code-copy")
        .remove()
        .end()
        .end();

    //复制按钮添加标题
    mdContentHtmlJq = mdContentHtmlJq.find(".markdown-it-code-copy")
        .text("复制")
        .end();


    return mdContentHtmlJq.prop("outerHTML");
}

/**
 * md转HTML之后事件处理修正
 * @param mdContentHtml
 * @returns {*|jQuery}
 */
function mdContentHtml2EventCorrection(mdContentHtml) {
    //复制成功后的提示
    $(document).delegate(".markdown-it-code-copy", "click", function() {
        layer.msg('复制成功', {time: 1000, icon:6});
    })

    //文章导航栏页面跳转
    $(document).delegate(".articleDetailPage .content-wrapper a", "click", function() {
        let anchorId = $(this).attr('href')
        if(strIsNotEmpty(anchorId)) {
            anchorId = anchorId.substr(1)
            log(`文章锚点跳转:${anchorId}`)
            $(`:header[id='${anchorId}']`)[0].scrollIntoView(true)
        }
        return false;
    })


    //侧边导航栏页面样式逻辑
    $(document).delegate(".article-slide-nav a", "click", function() {
        $(this)
            .parents(".article-slide-nav")
            .find("a")
            .css({
                color: 'var(--default-a-color)'
            });
        $(this).css({
            color: 'var(--default-a-clicked-color)'
        })
        return false;
    })


    return mdContentHtml;
}

/**
 * md转HTML-markdown-it方式
 * <a href="https://www.npmjs.com/package/markdown-it" />
 * @param mdContent
 * @returns {null|*|Window.jQuery}
 */
function mdToHtml2(mdContent) {

    mdToHtml2ConfigInit();

    if(strIsNotEmpty(mdContent)) {
        log('原始markdown内容:', mdContent)

        let mdContentHtml = mdToHtmlGenerator2.render(mdContent)


        mdContentHtmlJquery = $("<div class='content-wrapper' />")
            .append(mdContentHtml);

        //mermaid语法转换成svg在页面显示
        mdContentHtml = $(mdContentHtmlJquery).find(".mermaid").each(function(mermaidIndex) {
            let content = $(this).text();
            log('mermaid语法内容:', content)
            let renderContent = mermaid.render('mermaid' + mermaidIndex, content)
            log('mermaid语法渲染后的内容:', renderContent)
            $(this).html(renderContent)
        }).end().prop("outerHTML")


        mdContentHtml = mdContentHtml2AddSlideNav(mdContentHtml)
        mdContentHtml = mdContentHtml2EventCorrection(mdContentHtml)
        mdContentHtml = mdContentHtml2StyleCorrection(mdContentHtml)

        log('渲染后markdown内容:', mdContentHtml)
        return mdContentHtml;
    }


    return null;
}


index.html - 演示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="libs/highlight-11.6.0_all-language/styles/atom-one-dark.min.css" />
    <script src="libs/highlight-11.6.0_all-language/highlight.min.js"></script>

    <script src="libs/jquery.min.js"></script>
    <script src="libs/layer/layer.js"></script>


    <style>

        :root {

            --articleDetailPage-margintop: 5%;
            --articleDetailPage-margin: var(--articleDetailPage-margintop) auto;
            --articleDetailPage-marginright: 3%;


            --default-a-color: inherit;
            --default-a-clicked-color: rgb(0, 127, 255);
            --default-a-hover-color: red;
            --default-a-hover-backgroundcolor: #DEDEE5;
            --default-a-lineheight: 2rem;
        }

        ol,ul {
            list-style-type: none
        }
        a {
            text-decoration:none;
            color: var(--default-a-color);
            line-height: var(--default-a-lineheight);
        }
        a:visited {
            color: var(--default-a-color);
        }
        a:hover  {
            color: var(--default-a-hover-color) !important;
            background: var(--default-a-hover-backgroundcolor);
        }

        .article-content {
            width: 60%;
            box-shadow: 0px 0px 12px rgb(0 0 0 / 12%);
            margin: var(--articleDetailPage-margintop) auto;
            padding: 1rem;
        }
    </style>
</head>
<body>
<div class="article-content"></div>
</body>


<script src="libs/markdown-it/markdown-it.13.0.1.js"></script>
<script src="libs/markdown-it/markdownItAnchor.js"></script>
<script src="libs/markdown-it/markdownItTocDoneRight.js"></script>
<script src="libs/markdown-it/markdown-it-textual-uml.js"></script>
<!-- 特别注意这个不要放在head里面加载,否则代码复制不了,别问为什么,我也不知道,其他的都放在head里面应该没啥问题 -->
<script src="libs/markdown-it/markdown-it-code-copy.js"></script>
<script src="libs/markdown-it/markdown-it-emoji.js"></script>
<script src="libs/markdown-it/mermaid.js"></script>

<script src="js/markdownContentData.js"></script>
<script src="js/markdownUtils.js"></script>
<script>

    $(function () {
        //假设从后端拿到的markdown内容数据
        let currentMarkdownContentData = markdownContentData;

        console.log('markdown内容',currentMarkdownContentData)

        let currentMarkdownContentDataHtml = mdToHtml2(currentMarkdownContentData);

        console.log('渲染后的markdown内容',currentMarkdownContentDataHtml)

        $(".article-content").html(currentMarkdownContentDataHtml)
    })


</script>

</html>

在这里插入图片描述

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值