caoruiy‘s blog

Wisdom outweighs any wealth

wordpress-使用markdown+语法高亮的最佳组合(WP Markdown Editor+Prettify)

wordpress中后台编辑文章的工具很多,但是从业者大多喜欢使用 markdown 工具,推荐的编辑器插件很多,这里不会对众多工具做过多的比较,个人觉得 WP Markdown Editor 很好用,也是网上推荐最多的 markdown 编辑工具。

代码托管到github

项目地址:

https://github.com/caoruiy/google-prettify-monokai-theme-for-wordpress

WP Markdown Editor 安装

在后台插件中搜索关键字 WP Markdown Editor 即可
WP Markdown Editor

使用Google Code Prettify来显示语法高亮

语法高亮有很多插件,但是你想定制化的话还是需要自己动手来做,本博客的语法高亮就是自己贴代码实现的,当然,这个也是我从别的博客参照过来的(原文地址:http://www.powerxing.com/wordpress-markdown-plugin/)。

此处就是查看根据其源码修改而来,对于没有编码经验和能力的同学,本文的价值就在于手把手教会你自己去搭建自己的代码高亮。

第一步,引入Google Code Prettify

Google Code Prettify 是谷歌的代码高亮库,引入链接:

<!-- 引入JS文件 -->
<script src="//cdn.bootcss.com/prettify/r298/prettify.min.js"></script>

这里使用的是 cdn.bootcss.comCDN

第二步,引入样式表css文件

这里由于是对 prettify 做了一些定制,所以样式表文件不能引入 prettify 的主题。

我把代码托管到了 github 大家根据这里的链接,把这里的内容保存到本地,然后引入到页面中。

考虑到有些人访问 github 可能很慢,我会把css全部内容贴在本文的最后!

比如本博客,我把css文件保存在 wp-content/themes/kratos/css 中,只需要这样引入:

<!-- 替换href中的内容 -->
<link rel='stylesheet'  href='http://blog.plcent.com/wp-content/themes/kratos/css/google-prettify-monokai-theme-sub.css?ver=3.5.1' type='text/css' />

第三步,引入JS文件

因为我们要实现粘贴/复制的功能,所以还需要引入粘贴复制支持的库 clipboard.js V1.5.16

<script src="//cdn.bootcss.com/clipboard.js/1.5.16/clipboard.min.js"></script>

我把实现复制查看源码的功能都写在一个文件中,其内容在本文最后 (power.js)

把该内容 (power.js) 复制到文件保存后,就可以实现本博客的效果!!

wordpress 引入js/css文件写法:

也许有的人会有代码洁癖,希望JS和CSS的引入也是用WP的语法,下面就是使用WP语法引入的代码,如果你不需要,可以忽略这一段,没有任何影响。

define( 'CDN', '//cdn.bootcss.com' );
// 添加高亮需要的资源
function addCodeHighLight(){
    $dir = get_template_directory_uri(); 
    if ( !is_admin() ) {
        wp_enqueue_style( 'prettify-theme', $dir . '/css/google-prettify-monokai-theme-sub.css', array(), '3.3.7');
        wp_enqueue_script( 'prettify', CDN.'/prettify/r298/prettify.min.js', array(),  'r298');
        wp_enqueue_script( 'clipboard', CDN.'clipboard.js/1.5.16/clipboard.min.js', array(),  '1.5.16');
        wp_enqueue_script( 'power', CDN.'clipboard.js/1.5.16/power.js', array(),  '1.5.16');
    }
}
add_action('wp_enqueue_scripts', 'addCodeHighLight');

pwoer.js 源码

把下面的JS内容复制保存到文件 power.js

/**
 * 全站JS
 */
 window.onload = function(){
    var Global = {
    /*
     * 代码高亮的工具栏
     */
     codePrettifyToolbar: function(lang) {
        var _lang;
        switch( lang.toLowerCase() ) {
            case 'js':
            case 'javascript':
            _lang = 'JavaScript';
            break;
            case 'java':
            case 'python':
            case 'shell':
            _lang = lang.charAt(0).toUpperCase().concat(lang.toLowerCase().slice(1));
            break;
            case 'bash':
            _lang = 'Shell 命令';
            break;
            case 'c':
            _lang = 'C 语言';
            break;
            case 'html': 
            case 'css': 
            case 'xml':
            case 'cpp':
            _lang = lang.toUpperCase();
            break;
            default:
            _lang = lang; 
        }

        var toolbar = '<div class="code-pretty-toolbar">' +
        '<span class="title">' + _lang + '</span>' +
        '<a href="javascript:void(0);" title="复制代码" class="tool clipboard"><i class="fa fa-files-o"></i></a>' +
        '<a href="javascript:void(0);" title="查看纯文本代码" class="tool view-source"><i class="fa fa-code"></i></a>' +
        '<a href="javascript:void(0);" title="返回代码高亮" class="tool back-to-pretty"><i class="fa fa-undo"></i></a>' +
        '<span class="msg"></span>' +
        '</div>';

        return toolbar;
     },
    /*
     * 获取代码文本
     */
     getPrettifyCode: function($container) {
        code = [];

        // 组合代码
        $container.find('li').each(function() {
            code.push( $(this).text() );
        });
        // using \r instead of \r or \r\n makes this work equally well on IE, FF and Webkit
        code = code.join('\r');
        // For Webkit browsers, replace nbsp with a breaking space
        code = code.replace(/\u00a0/g, " ");

        return code;
    },
    /*
     * 代码高亮工具栏功能
     */
     codePrettifyToolbarAction: function() {
        /* 复制代码 */
        _this = this;
        var clipboard = new Clipboard('.clipboard', {
            text: function(e) {
                $container = $(e).parent().parent();
                return _this.getPrettifyCode($container);
            }
        });
        clipboard.on('success', function(e) {
            $container = $(e.trigger).parent().parent();
            $container.find('.msg').hide().text('已复制.').stop().fadeIn(300).delay(1500).fadeOut(500);
        });

        clipboard.on('error', function(e) {
            $container = $(e.trigger).parent().parent();
            $container.find('.msg').hide().text('暂不支持当前浏览器,请手动复制 (ctrl + c)').stop().fadeIn(300).delay(3000).fadeOut(500);
            $container.find('.view-source').trigger('click');
        });

        /* 其他事件 */
        $('.code-pretty-toolbar a').on('click', function() {
            /* 查看纯文本代码 */
            if ( $(this).hasClass('view-source') ) {
                $container = $(this).parent().parent();

                    // 获取代码文本
                    code = _this.getPrettifyCode($container);

                    // 填充 textarea
                    if ( !$container.find('textarea').length ) {
                        $container.append('<textarea class="code-pretty-text">' + code + '</textarea>');
                    } else {
                        $container.find('textarea').val(code);
                    }

                    // 调整 textarea 位置
                    var $pre = $container.find('pre');
                        if ( $pre.hasClass('lang-bash') ) { // bash 固定不变
                            var w = $pre.width() - 15;
                            var h = $pre.height() + 10;
                            var marginLeft = 32;
                        } else {
                            var liCount = $pre.find('li').length;
                            var offset = liCount / 1000;
                            var w = $pre.width() - 30 - 5*offset
                            var h = $pre.height() + 10;
                            var marginLeft = 53 + 5*offset;
                        }

                    // 显示 textarea
                    $container.find('textarea').css({height: h, width: w, 'margin-left': marginLeft})
                    .show().select();

                    $container.find('.view-source').hide();
                    $container.find('.back-to-pretty').css('display', 'inline-block');

                } else if ( $(this).hasClass('back-to-pretty') ) {
                    $container.find('.back-to-pretty').hide();
                    $container.find('.view-source').css('display', 'inline-block');

                    $container.find('textarea').hide();
                }
            });
     },
     /* 增加 bash 高亮规则 */
     codePrettifyAddBash: function() {
        /* 不完善的实现 */
        PR['registerLangHandler'](
            PR['createSimpleLexer'](
                [
                // Whitespace
                [PR['PR_PLAIN'],       /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
                // A double or single quoted, possibly multi-line, string.
                [PR['PR_STRING'],      /^(?:"(?:[^\"\\]|\\.)*"|'(?:[^\'\\]|\\.)*')/, null,
                '"\'']
                ],
                [
                [PR['PR_COMMENT'], /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#'],
                [PR['PR_KEYWORD'], /[^\.\/]?(?:ls|cd|chown|chmod|sudo|su|vi|vim|cat|touch|tar|scp|cp|ssh|useradd|passwd|apt\-get|export|source|echo|mv|mkdir|rm)(\s)+/i, null],
                // [PR['PR_LITERAL'],
                 // /^([^a-zA-Z0-9](-(\w)*))|\$(\w)*/i],
                // An identifier
                [PR['PR_PLAIN'], /^[a-z_][\w-]*/i],
                // A run of punctuation
                // [PR['PR_PUNCTUATION'], /^[^\w\t\n\r \xA0\"\'][^\w\t\n\r \xA0+\-\"\']*/]
                ]),
            ['bash', 'sh', 'shell']);
     },
    /*
     * 代码高亮 Google Code Prettify
     */
     codePrettify: function() {
        /* 更改 pre 的 class,增加 toolbar */
        var _this = this;
        $('pre code').each(function() {
            var lang = $(this).attr('class');
            if (lang) {
                var code = $(this).html();
                $(this).parent().attr('class', 'prettyprint linenums lang-' + lang).html(code)
                .wrap('<div class="code-pretty-container"></div>')
                .parent().append( _this.codePrettifyToolbar(lang) );
            }
        });
        this.codePrettifyAddBash();
        PR.prettyPrint();
        this.codePrettifyToolbarAction();
     },
     init: function() {
        this.codePrettify();
     }
    };
    Global.init();
 };

提示:
网上的很多教程都说引入文件后要调用:

prettyPrint();

这里不建议大家这样调用了,因为这个函数并不存在,在当前的版本里。

css源码

CSS代码用来控制站点中展示的风格,你也可以自己修改某些代码。

这里的样式也是使用了 代码高亮的皮肤 google-prettify-monokai-theme 并根据本博客内容,做了一些定制,你拿回去之后,也可以自己定制哦。详细参见下面文件中的注释。


/** * 修正wordpress的默认样式 */ code { border: 1px solid transparent; } pre { background-color: transparent; border-radius: 4px !important; } /** * 高亮工具条样式 */ .code-pretty-container{ position: relative; padding-top: 12px; } .code-pretty-toolbar { position: absolute; top: 0; left: 0; font-size: 12px; color: #ddd; } .code-pretty-text { position: absolute; top: 38px; left: 0px; padding: 4px; color: #FFF; font-family: consolas, menlo, courier, monospace; word-break: break-all; line-height: 20px; border: none; overflow: hidden; background-color: rgb(39, 40, 34); resize: none; } .code-pretty-toolbar .title { background-color: #1E1F1A; box-shadow: inset 2px 3px 1px 0px #3c3d39, 0 -1px 12px rgba(0,0,0,0.5); border: 1px solid #0b0c0a; padding: 4px 14px 2px; border-radius: 8px 8px 0 0; border-bottom: none; margin-right: 12px; } .code-pretty-toolbar .tool { font-size: 16px; color: #777777; width: 24px; height: 24px; margin: -1px 3px 0 0; } .code-pretty-toolbar span, .code-pretty-toolbar a { display: inline-block; vertical-align: top; } .code-pretty-toolbar span, .code-pretty-toolbar a { display: inline-block; vertical-align: top; } /* * 代码高亮 * google-prettify-monokai-theme */ /* ======================== //#google-prettify-monokai-theme //#Version: 0.3 //#Author: RaphaelDDL //#Github: https://github.com/RaphaelDDL/google-prettify-monokai-theme/ //For use with Google Code Prettify, HTML Syntax only //======================== */ pre .kwd, code .kwd { color: #66d9ef; } /* keyword */ pre .com, code .com { color: #75715e; font-style: italic; } /* comment */ pre .typ, code .typ { color: #66d9ef; } /* type */ pre .lit, code .lit { color: #ae81ff; } /* literal */ pre .pun, code .pun { color: #fff; } /* punctuation */ pre .pln, code .pln { color: #fff; } /* plaintext */ pre .tag, code .tag { color: #f92672; } /* html/xml tag */ pre .atn, code .atn { color: #a6e22a; } /* html/xml attribute name */ pre .atv, code .atv { color: #e6db74; } /* html/xml attribute value */ pre .dec, code .dec { color: #ae81ff; } /* decimal */ pre .str, code .str { color: #e6db5a; } /* string */ pre.prettyprint, code.prettyprint { background-color: #272822; -moz-border-radius: 8px; -webkit-border-radius: 8px; -o-border-radius: 8px; -ms-border-radius: 8px; -khtml-border-radius: 8px; border-radius: 8px; font-family: consolas, menlo, courier, monospace; } pre.prettyprint { width: 100%; margin: 1em auto; padding: 1em; white-space: pre-wrap; } pre.prettyprinted { box-shadow:inset 0 0 1px 2px #3c3d39, 0 0 15px rgba(0,0,0,0.5); border:1px solid #0b0c0a; } /* ------------------------ //Section: class 'linenums' for line numbering //------------------------ */ ol.linenums { margin-top: 0; margin-bottom: 0; color: #75715e; list-style-type: decimal inside !important; } /* IE indents via margin-left */ /* ============================================= //Section: Print Styles (partially from Sunburn Theme) //================================================ */ @media print { pre.prettyprinted, pre.prettyprint, code.prettyprint { background-color:#fff; color:#000; -moz-border-radius:0; -webkit-border-radius:0; -o-border-radius:0; -ms-border-radius:0; -khtml-border-radius:0; border-radius:0; } pre .str, code .str { color: #060; } pre .kwd, code .kwd { color: #006; font-weight: bold; } pre .com, code .com { color: #600; font-style: italic; } pre .typ, code .typ { color: #404; font-weight: bold; } pre .lit, code .lit { color: #044; } pre .pun, code .pun { color: #440; } pre .pln, code .pln { color: #000; } pre .tag, code .tag { color: #006; font-weight: bold; } pre .atn, code .atn { color: #404; } pre .atv, code .atv { color: #060; } }
点赞
  1. young说道:

    博主您好,我在尝试着按照您写的这篇博文完成代码高亮功能的时候发现了两个小问题。第一个是您在添加高亮需要的资源的那段代码中所添加的js文件的有几个是不能用了,无法加载,第二个是您的博文中没有清楚的说明能够引起渲染的代码的格式。

  2. 白狼syc说道:

    写的很好,非常感谢分享,我用了和你一样的主题,代码高亮也设置成功了。
    你的文章页取消sidebar后如何调整显示宽度啊,还有那个顶部菜单栏点击web前端弹出下拉框那个怎么实现的?

    1. caoruiy caoruiy说道:

      主题自带的功能,菜单编辑里有 :eek:

  3. 白狼syc说道:

    写的很好,非常感谢分享,我用了和你一样的主题,代码高亮也设置成功了。
    你的文章页取消sidebar后如何调整显示宽度啊,还有那个顶部菜单栏点击web前端弹出下拉框那个怎么实现的?

    1. caoruiy caoruiy说道:

      这个是自己写的JS,代码放在了power.js中,你可以去找下具体的内容。

      具体实现在下年这个方法里:

      /**
       * 修改文章宽度
       */
      function changeBlogWidth(){
          var width_pc = $('<a href="javascript:;" class="cd-gb-a" id="width-pc"></a>').css({
              'bottom':'208px',
          }).append('<span class="fa fa-arrows-alt"></span>').css({
              'margin-top': '16px',
              'color': '#fff',
              'font-size': '20px',
          }).append($('<div id="width-over">隐藏侧边栏</div>').css({
              'position': 'fixed',
              'right': '100px',
              'bottom': '210px',
              'width': '150px',
              'background':"rgb(166, 166, 166)",
              'padding':'5px 10px',
              'color':'#FFF',
              'display':'none',
          }))
      
          $(".cd-tool").prepend(width_pc)
      
          $("#width-pc").mouseover(function(){
              $("#width-over")[0].style.display = 'block';
          }).mouseout(function(){
              $("#width-over")[0].style.display = 'none';
          }).click(function(){
              if(!$("#main").hasClass('col-md-12')){
                  $("#main").addClass('col-md-12').removeClass('col-md-8')
                  $("#kratos-widget-area").addClass('hidden-md').addClass('hidden-lg');
                  $("#width-over").html('显示侧边栏');
              }else{
                  $("#main").addClass('col-md-8').removeClass('col-md-12')
                  $("#kratos-widget-area").removeClass('hidden-md').removeClass('hidden-lg');
                  $("#width-over").html('隐藏侧边栏');
              }
          })
      }
      
  4. 白狼426说道:

    文章写的很好,同样步骤,我在别的主题实现的代码高亮效果有点bug,但是换成和你一样的主题就没问题了.
    你的这个文章页面去掉右侧sidebar后如何调整文章的宽度.还有右下脚的哪个点击微信图标弹出图片怎么实现的.

  5. aliben说道:

    博主,你好。看了你的代码高亮,效果非常惊艳。但关于第一第二步的引入css和js文件的代码,应该将代码引入到那个文件里呢?看下几遍还是没找到文件引入的位置说明,web编程没接触过,能否麻烦详细说一下需要修改那几个文件吗? 谢谢🙏

    1. caoruiy caoruiy说道:

      这个问题非常深刻,值得好好说一下。打个比方,你想在A页面中有高亮效果,是不是代码就应该在A页面中引用呢?虽然这不是唯一的答案,但考虑到你是新手,可以这样做,把所有高亮用到的代码,都在需要的页面引入进来。CSS文件在之间引入。JS代码在之前引入即可。

  6. stanley说道:

    详情页是哪个啊?single.php吗?
    我放进去之后,没有多大变化啊。。
    你看这个文章http://blog.stanleywind.com/google-code-prettify/

    1. caoruiy caoruiy说道:

      这个,你再试试吧,我试过了,可以的。打开这个页面(http://blog.stanleywind.com/google-code-prettify/)的时候,添加上我上一次回复你的内容,基本就可以了。

  7. Stanley说道:

    楼主,请教问题:
    1. 你那段 “wordpress 引入 js / css 文件写法” 的代码是干嘛用的,不是只要加入一句调用pretty的话不就可以了吗?没明白这段。
    2. 所有都弄完后,添加代码怎么弄呢?Md的```添加进去根本不识别,手动添加code之后,比如 printf("hello, world\n"); ,会识别错误。只有换为转义符后才会显示成功,比如 printf("hello world\n");,看你的源码,你的会自动添加span,这样是如何做到的呢?

    1. caoruiy caoruiy说道:

      那一段其实不用管,因为使用WP的人,可能会希望使用WP的语法引入JS和CSS,所以给出了那一段,你可以使用那一段代码引入JS和CSS。当然,你也可以使用原始的方法引入JS和CSS文件。

      其中,所有需要引入的文件有:google的代码高亮库,实现粘贴复制功能,需要引入clipboard.js,之后就是控制样式的CSS文件,和自己实现功能的power.js,也就是博客后面贴的代码,这四个文件帖进去之后就没有问题了。

      你可以看看哪里报错,再做修改。

      写代码要用下面的格式:

      ```html
      ```
      

      标明这段代码是什么语言的。

      1. Stanley说道:

        搞定了,但是还是有一个bug。
        就是有时候第一次加载的时候,代码包裹的div不添加class,这就导致,CSS样式没加载上。
        当第二次刷新的时候,就会添加class并成功加载css了。
        这是咋回事呢?

        1. caoruiy caoruiy说道:

          有可能代码加载顺序的问题,你页面还没显示完,高亮就执行完了,把语法高亮的JS代码放到最后,CSS代码放在最前面。

          1. Stanley说道:

            依旧不行啊,不管放哪,首次加载就是不出来样式,必须手动刷新一下。
            那些js是放在footer.php里咯?

          2. caoruiy caoruiy说道:

            你有没有地址,我可以帮你看一下

          3. Staney说道:

            blog.stanleywind.com
            麻烦你帮我看下哈,实在非常感谢

          4. caoruiy caoruiy说道:

            我看了你的代码,你把高亮的相关代码放在了首页中加载进来,但是点击进入各个详细文章时,并没有执行任何JS代码,所以,你有两个解决办法:

            1. 把代码高亮的JS放在各个文章详情页加载进来
            2. 在文章详情页主动触发代码高亮的power.js中的代码

            针对第二种:你把你power.js最后三行:

            Global.init();
            /* class加样式 */
            jQuery("pre").addClass("prettyprint linenums");
            prettyPrint();
            

            修改成:

            /* class加样式 */
            jQuery("pre").addClass("prettyprint linenums");
            window.Power = Global;
            

            然后在每一个文章详情页执行:

            Power.init()
            

            就OK👌啦,最后还有,你的博客没法评论!!😆😀

  8. 爱飞的小猫说道:

    很好的文章,感谢分享。。。
    😊😊😊😊

发表评论

电子邮件地址不会被公开。 必填项已用*标注