当前位置:秋叶网络博客 前端设计 ◊ 用Javascript给文本段落加上p标签实现换行

用Javascript给文本段落加上p标签实现换行

作者:秋叶 发表时间:2017年8月05日

最近在用node重写我的博客(憔悴了许多),既然从wordpress转过来的,wordpress基本功能还是不能变的,无形中加大了开发难度。比如说加密算法,数据表关系串联,数据库高并发IO性能优化。。。等等一大堆需要解决的问题,要做就要做最好的,用最优的方法,最快的算法,最安全的code来以太阳肩并肩。起初以为增删改查就完事了,其实没那么简单。就连读取文章看似很简单的事情其实并不是想象那样,直接从数据库里面读取出来的文章内容是不会换行的,尤其是没有标签的内容但是又换行了,这着实有点尴尬。

起初在分析换行的种种情况,思来想去突然明白了一个真理,直接看wordpress实现过程吧~,翻到他的源码,发现wordpress作者对文章内容处理做了孜孜不倦的字符串算法~,没错,就加一个p标签小小的事情,可是并不简单。它要考虑到各种标签,把它切割重组抛光打蜡,最后给你return一个完美的内容。以下是我把那个php处理函数转成javascript的代码:

function autop($pee, $br) {
    var $pre_tags = {};
    var trim = function(str) {
        return str.replace(/(^\s*)|(\s*$)/g, "");
    }
    if ( trim($pee) === '' ){
        return '';
    }

    $pee = $pee + "\n"; // just to make things a little easier, pad the end

    if ($pee.indexOf('<pre') !== -1) {
        var $pee_parts = $pee.split('</pre>');
        var $last_pee = $pee_parts.pop();
        $pee = '';
        var $start,$name;
        for(var i = 0, len = $pee_parts.length; i < len; i++){
            $start = $pee_parts[i].indexOf('<pre');

            // Malformed html?
            if ( $start === -1 ) {
                $pee += $pee_parts[i];
                continue;
            }

            $name = "<pre wp-pre-tag-"+i+"></pre>";
            $pre_tags[$name] = $pee_parts[i].substr($start) + '</pre>';

            $pee += $pee_parts[i].substr(0, $start ) + $name;
        }

        $pee += $last_pee;
    }

    $pee = $pee.replace(new RegExp('<br \/>\\s*<br \/>','gi'), "\n\n");
    var $allblocks = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|form|map|area|blockquote|address|math|style|p|h[1-6]|hr|fieldset|legend|section|article|aside|hgroup|header|footer|nav|figure|details|menu|summary)';
    $pee = $pee.replace(new RegExp('(<' + $allblocks + '[^>]*>)','gi'), "\n$1");
    $pee = $pee.replace(new RegExp('(<\/' + $allblocks + '>)','gi'), "$1\n\n");
    $pee = $pee.replace(/(\r\n|\r)/gi, "\n"); // cross-platform newlines

    if ( $pee.indexOf('<option') !== -1) {
        // no P/BR around option
        $pee = $pee.replace(/\s*<option/gi, '<option');
        $pee = $pee.replace(/<\/option>\s*/gi, '</option>');
    }

    if ( $pee.indexOf('</object>' ) !== -1 ) {
        // no P/BR around param and embed
        $pee = $pee.replace(/(<object[^>]*>)\s*/gi, '$1');
        $pee = $pee.replace(/\s*<\/object>/, '</object>');
        $pee = $pee.replace(/\s*(<\/?(?:param|embed)[^>]*>)\s*/gi, '$1');
    }

    if ( $pee.indexOf('<source') !== -1 || $pee.indexOf('<track') !== -1 ) {
        // no P/BR around source and track
        $pee = $pee.replace(/([<\[](?:audio|video)[^>\]]*[>\]])\s*/gi, '$1');
        $pee = $pee.replace(/\s*([<\[]\/(?:audio|video)[>\]])/gi, '$1');
        $pee = $pee.replace(/\s*(<(?:source|track)[^>]*>)\s*/gi, '$1');
    }

    $pee = $pee.replace(/\n\n+/, "\n\n"); // take care of duplicates
    // make paragraphs, including one at the end
    $pees = $pee.split(/\n\s*\n/).filter(function(item){
        return (item!=false);
    });
    $pee = '';

    for(var i =0,len = $pees.length; i < len; i++){
        $pee += '<p>' + trim($pees[i], "\n") + "</p>\n";
    }

    $pee = $pee.replace(/<p>\s*<\/p>/gi, ''); // under certain strange conditions it could create a P of entirely whitespace
    $pee = $pee.replace(/<p>([^<]+)<\/(div|address|form)>/gi, "<p>$1</p></$2>");
    $pee = $pee.replace(new RegExp('<p>\s*(<\/?' + $allblocks + '[^>]*>)\s*<\/p>','gi'), "$1"); // don't pee all over a tag
    $pee = $pee.replace(/<p>(<li.+?)<\/p>/gi, "$1"); // problem with nested lists
    $pee = $pee.replace(/<p><blockquote([^>]*)>/gi, "<blockquote$1><p>");
    $pee = $pee.replace('</blockquote></p>', '</p></blockquote>');
    $pee = $pee.replace(new RegExp('<p>\s*(<\/?' + $allblocks + '[^>]*>)','gi'), "$1");
    $pee = $pee.replace(new RegExp('(<\/?' + $allblocks + '[^>]*>)\s*</p>','gi'), "$1");

    if ( $br ) {
        //$pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee);
        $pee = $pee.replace(/<br \/>\s*\n/, "<br />\n"); // optionally make line breaks
        $pee = $pee.replace('<WPPreserveNewline />', "\n");
    }

    $pee = $pee.replace(new RegExp('(</?' + $allblocks + '[^>]*>)\s*<br />','gi'), "$1");
    $pee = $pee.replace(/<br \/>(\s*<\/?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)/gi, '$1');
    $pee = $pee.replace(/\n<\/p>$/, '</p>');
    if (!$pre_tags.length){
        for(var i in $pre_tags){
            if($pre_tags.hasOwnProperty(i)){
                $pee = $pee.replace(i, $pre_tags[i]);
            }
        }
    }
    return $pee;
}

使用的话autop(content);content为需要处理的内容。

目录: 前端设计 | 标签: | 2883次阅读