• JavaScript笔记 #08# 用Regex辅助生成文章目录 V2.0


    简介

                 * 用Regex辅助生成文章目录 2.0
                 * 1、提高了功能的通用性(假定的文章格式更加普遍,即按照h2h3h4分级)
                 * 2、改善了代码的可读性
                 * 3、略微。。提高了扩展性(只需要重写generateDirectory方法就可以
                 * 生成自定义目录)
                 * 缺点:没有处理比较脏的情况,需要人工确保html干净

    测试用例

    输入:

            <h2>你好</h2>
            <p>dasjdalsjdlsasjdlsczxcnzxczxczxc00</p>
            <h3>dasda</h3>
            <h4>23981023812090839dajldjasldjalsjd</h4>
            <p>dasdasjdlasjdlasjdlassjdalsdjalsdj</p>
            <h4>21023812038129dajldjasldjalsjd</h4>
            <p>dasdassjdlasjdlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlasjddlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlasjdlasjdlasjdalsdjalsdj</p>
            <h3>ddada</h3>
            <p>dasdasjdlasjdlasjdlasjdalsdjalsdj</p>
            <p>daasjdlasjdlasjdlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlasjdlasdlasjdalsdjalsdj</p>
            <h2>hi</h2>
            <h3>dadasdasda</h3>
            <p>dasdasjdlasjdljdlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlasjdsjdlasjdalsdjalsdj</p>
            <p>dasdasjjdlasjdlasjdlasjdalsdjalsdj</p>
            <h3>dasasdassaddasda</h3>
            <p>dasdasjdlasasjdlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlalasjdlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlasjdlasjdlasjdlasjdalsdjalsdj</p>
            <h2>大家好</h2>
            <p>asjdlasjdlaasjdlasjsdjalsdj</p>
            <p>dsjdlasjdlasjdldlasjdalsdjalsdj</p>
            <p>dasdasjdlasjdlasjdalsdjalsdj</p>

    输出:

    <div id="diy_right_menu">
    <h2>索引</h2>
    <ul>
    <ol><li><a href="#anchor0">你好</a>
    <ul><li><a href="#anchor1">dasda</a>
    <ul><li><a href="#anchor2">23981023812090839dajldjasldjalsjd</a></li>
    <li><a href="#anchor3">21023812038129dajldjasldjalsjd</a></li>
    </ul>
    </li>
    <li><a href="#anchor4">ddada</a></li>
    </ul>
    </li>
    <li><a href="#anchor5">hi</a>
    <ul><li><a href="#anchor6">dadasdasda</a></li>
    <li><a href="#anchor7">dasasdassaddasda</a></li>
    </ul>
    </li>
    <li><a href="#anchor8">大家好</a></li>
    </ol>
    </ul>
    </div>
                    <h2><a name="anchor0"></a>你好</h2>
            <p>dasjdalsjdlsasjdlsczxcnzxczxczxc00</p>
            <h3><a name="anchor1"></a>dasda</h3>
            <h4><a name="anchor2"></a>23981023812090839dajldjasldjalsjd</h4>
            <p>dasdasjdlasjdlasjdlassjdalsdjalsdj</p>
            <h4><a name="anchor3"></a>21023812038129dajldjasldjalsjd</h4>
            <p>dasdassjdlasjdlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlasjddlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlasjdlasjdlasjdalsdjalsdj</p>
            <h3><a name="anchor4"></a>ddada</h3>
            <p>dasdasjdlasjdlasjdlasjdalsdjalsdj</p>
            <p>daasjdlasjdlasjdlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlasjdlasdlasjdalsdjalsdj</p>
            <h2><a name="anchor5"></a>hi</h2>
            <h3><a name="anchor6"></a>dadasdasda</h3>
            <p>dasdasjdlasjdljdlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlasjdsjdlasjdalsdjalsdj</p>
            <p>dasdasjjdlasjdlasjdlasjdalsdjalsdj</p>
            <h3><a name="anchor7"></a>dasasdassaddasda</h3>
            <p>dasdasjdlasasjdlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlalasjdlasjdlasjdalsdjalsdj</p>
            <p>dasdasjdlasjdlasjdlasjdlasjdalsdjalsdj</p>
            <h2><a name="anchor8"></a>大家好</h2>
            <p>asjdlasjdlaasjdlasjsdjalsdj</p>
            <p>dsjdlasjdlasjdldlasjdalsdjalsdj</p>
            <p>dasdasjdlasjdlasjdalsdjalsdj</p>

    代码

    追加,偶尔会出现BUG,有序列表与无序列表有时候会乱用。仍需人工检查、修正。

    <!DOCTYPE html>
    <html>
    
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
    
        <body>
            <textarea id="big-textarea" placeholder="paste your origin html text here..." rows="30" cols="150">
            </textarea>
            <button id="big-button">Generate</button>
            
            <script type="text/javascript">
                /**
                 * 用Regex辅助生成文章目录 2.0
                 * 1、提高了功能的通用性(假定的文章格式更加普遍,即按照h2h3h4分级)
                 * 2、改善了代码的可读性(稍微牺牲了一点点性能,不过也无关紧要。。。)
                 * 3、略微。。提高了扩展性(只需要重写generateDirectory方法就可以
                 * 生成自定义目录)
                 * 缺点:没有处理比较脏的情况,需要人工确保html干净
                 */
                let button = document.querySelector('#big-button');
                button.addEventListener('click', event => {
                    let textArea = document.querySelector('#big-textarea');
                    let inputHtml = textArea.value;
                    textArea.value = addDirectoryTo(inputHtml);
                });
            </script>
                    
            <script type="text/javascript">                    
                /**
                 * 返回生成目录后的inputHtml
                 * @param {Object} inputHtml 原始html
                 */
                function addDirectoryTo(inputHtml) {
                    // 给h2 h3 h4加上锚点
                    let modifiedHtml = addAnchorTo(inputHtml);
                    // 提取h2 h3 h4标题
                    let titles = extractTitles(inputHtml);
                    // 利用h2 h3 h4标题生成目录
                    let directory = generateDirectory(titles);
                    // 将目录和修改后的html拼接后返回
                    return directory + modifiedHtml;
                }
            </script>
     
             <script type="text/javascript">
                /**
                 * Title类属性↓
                 * text:string,存该标题中的文字
                 * level:Number,标题等级
                 * subTitles:list,用来存子标题
                 */
                function Title(h2h3h4) {
                    /**
                     * 构造器调用示例:new Title("<h2>二级标题</h2>")
                     */
                    if (h2h3h4 != undefined) {
                        let extractedInfo = this.patternOfh2h3h4.exec(h2h3h4);
                        this.text = extractedInfo[2];
                        this.level = Number(extractedInfo[1]);
                        this.subTitles = [];                    
                    }
                }
                
                Title.prototype.patternOfh2h3h4 = /<h([234])>([^]+?)</h[234]>/;
            </script>
            
            <script type="text/javascript">
                /**
                 * 返回给h2 h3 h4加上锚点后的html
                 * @param {Object} inputHtml 原始html
                 */
                function addAnchorTo(inputHtml) {
                    let patternOfh2h3h4 = /(<h[234]>)/g;
                    let indexOfAnchor = 0;
                    let modifyh2h3h4 = (_, h2h3h4) => {
                        return `${h2h3h4}<a name="anchor${indexOfAnchor++}"></a>`;
                    };
                    let modifiedHtml = inputHtml.replace(patternOfh2h3h4, modifyh2h3h4);
                    return modifiedHtml;
                }
                
                /**
                 * 返回包含二级标题对象的list 
                 * @param {Object} inputHtml 原始html
                 */
                function extractTitles(inputHtml) {                        
                    let titles = [];
                    let patternOfh2h3h4 = /<h[234]>[^]+?</h[234]>/g; // 非贪婪匹配
                    // 遍历正则匹配项
                    let match;
                    while (match = patternOfh2h3h4.exec(inputHtml)) {
                        let title = new Title(match[0]);
                        properPostion(titles, title.level).push(title);
                    }
                    return titles;
                }
                
                const TOP_LEVEL = 2;
                /**
                 * 返回某个标题的subTitles或者最终的titleList
                 * 给标题找合适的插入位置,为了不让extractTitles太长才抽象出来的。
                 * @param {Object} titles 
                 * @param {Object} level 待插入标题的level
                 */
                function properPostion(titles, level) {
                    for (let i = TOP_LEVEL; i != level; ++i) {
                        titles = titles[titles.length - 1].subTitles;                            
                    }
                    return titles;               
                }
    
                /**
                 * 返回根据标题生成的目录,这个方法可以根据需要自定义
                 * @param {Object} titles 包含二级标题对象的list 
                 */
                function generateDirectory(titles) {
                    return generateDiy_right_menu(titles);
                }         
                
                function generateDiy_right_menu(titles) {                
                    let indexOfAnchor = 0;
                    let divBody = "";
                    let visitTitle = function(title, first=false) {
                        if (!first) {
                            divBody += `<li><a href="#anchor${indexOfAnchor++}">${title.text}</a>`;                        
                        }                    
                        if (title.subTitles.length != 0) {
                            if (!first) {
                                divBody += '
    <ul>';
                            } else {
                                divBody += '
    <ol>';
                            }
                            for (let i = 0; i != title.subTitles.length; ++i) {
                                visitTitle(title.subTitles[i]);
                            }    
                            if (!first) {
                                divBody += '</ul>
    ';
                            } else {
                                divBody += '</ol>
    ';
                            }
                        }    
                        if (!first) {
                            divBody += '</li>
    ';
                        }
                    }            
                    let root = new Title(); // 便于遍历titles
                    root.subTitles = titles;
                    visitTitle(root, true);
                    
                    let divHead = '<div id="diy_right_menu">
    <h2>索引</h2>
    <ul>
    ';
                    let divTail = '</ul>
    </div>
    ';
                    return divHead + divBody + divTail;
                }
            </script>
        </body>
    
    </html>
  • 相关阅读:
    Mysql5.6主从复制-基于binlog
    mysql 1449 : The user specified as a definer ('root'@'%') does not exist 解决方法
    socket recv阻塞与非阻塞error总结
    linux socket talkclient talkserver示例
    linux-socket connect阻塞和非阻塞模式 示例
    OPENSSL FIPS
    epoll的LT和ET使用EPOLLONESHOT
    如何在socket编程的Tcp连接中实现心跳协议
    linux网络编程:splice函数和tee( )函数高效的零拷贝
    Linux网络编程--sendfile零拷贝高效率发送文件
  • 原文地址:https://www.cnblogs.com/xkxf/p/10012528.html
Copyright © 2020-2023  润新知