JS-多組關鍵詞列表高亮

来源:https://www.cnblogs.com/Raincry/archive/2020/06/26/13196210.html
-Advertisement-
Play Games

/** * 多個關鍵詞列表高亮(word_list1,color1,word_list2,color2,...) * @param word_list 關鍵詞列表(例: ["關鍵詞a","關鍵詞b"],不區分大小寫) * @param color 顏色值(例: "#ff0000") * @retur ...


/**
 * 多個關鍵詞列表高亮(word_list1,color1,word_list2,color2,...)
 * @param word_list 關鍵詞列表(例: ["關鍵詞a","關鍵詞b"],不區分大小寫)
 * @param color     顏色值(例: "#ff0000")
 * @returns {{render: Function}}
 * 優先順序:word_list1>word_list2>word_list3...
 * @example
 * var highlight = new wordHighlight(["B","C"],"#ff0000",["ABC","DEF"],"blue");
 * console.log(highlight.render("ABC")); // <b style="color:blue">A</b><b style="color:#ff0000">BC</b>
 * console.log(highlight.render("Bc,DEF")); // <b style="color:#ff0000">Bc</b>,<b style="color:blue">DEF</b>
 */
function wordHighlight(word_list,color)
{
    if (!(this instanceof wordHighlight)) {
        throw 'should be called with the new!';
    }
    var that = this;

    that.root        = null;
    that.color_list  = [];
    that.color_range = null;

    var createNode = function(value){
        var node   = {};
        node.value = value || "";
        node.next  = {};
        node.fail  = null;
        node.len   = 0; // word長度,0表示非末尾,非0表示word的長度
        node.color = -1;
        return node;
    }

    var addWord = function(word,color){
        word = word.trim().toLowerCase();
        if (!word) {
            return;
        }
        var cur = that.root;
        var len = word.length;
        for (var i = 0,v; i < len; i++) {
            v = word[i];
            if (cur.next[v] === undefined) {
                node = createNode(v);
                cur.next[v] = node;
            }
            cur = cur.next[v];
        }
        cur.len = len;
        if (cur.color == -1) {
            cur.color = color;
        }
    }

    var buildFailIndex = function(){
        var queue = [];
        var key;
        for (key in that.root.next) {
            that.root.next[key].fail = that.root;
            queue.push(that.root.next[key]);
        }
        while (queue.length) {
            node = queue.shift();
            for (key in node.next) {
                var child_node = node.next[key];
                var val = child_node.value;
                var p = node.fail;
                while (p != null) {
                    if (p.next[val] !== undefined) {
                        child_node.fail = p.next[val];
                        break;
                    }
                    p = p.fail;
                }
                if (p === null) {
                    child_node.fail = that.root;
                }
                queue.push(child_node);
            };
        }
    }

    var mergeRange = function(color,range_list){
        if (!range_list || !range_list.length) {
            return;
        }
        range_list = (function(input_list){
            // 區間合併
            var output_list = [];
            var tmp = {}, left = -1, right = -1;
            input_list.forEach(function(range){
                var start = range[0], end = range[1];
                if (tmp[start] === undefined || tmp[start] < end) {
                    tmp[start] = end;
                }
            });
            for (var start in tmp) {
                var end = tmp[start];
                if (left == -1) {
                    left = 0 | start;
                    right = end;
                }
                if (start > right) {
                    output_list.push([left,right])
                    left = 0 | start;
                    right = end;
                } else if (end > right) {
                    right = end;
                }
            }
            if (left != -1) {
                output_list.push([left, right])
            }
            return output_list;
        })(range_list);
        if (that.color_range === null) {
            that.color_range = {};
            range_list.forEach(function(v){
                that.color_range[v[0]] = [v[1],color];
            });
        } else {
            var xy_list = [0],x,y;
            for (var x in that.color_range) {
                xy_list.push(0|x);
                xy_list.push(that.color_range[x][0]);
            }
            xy_list.push(Infinity);
            //console.log(xy_list);
            var i = 0,len = range_list.length;
            do {
                x = xy_list.shift();
                y = xy_list.shift();
            } while (x == y);
            var _x,_y;
            while (i < len) {
                _x = range_list[i][0];
                _y = range_list[i][1];
                if (y < _y) {
                    if (_x < y) {
                        that.color_range[_x < x ? x : _x] = [y,color];
                    }
                    do {
                        x = xy_list.shift();
                        y = xy_list.shift();
                    } while (x == y);
                    continue;
                }
                if (_y > x) {
                    that.color_range[_x < x ? x : _x] = [_y,color];
                }
                i++;
            }
        }
    }

    that.root = createNode();

    var args = Array.prototype.slice.call(arguments);
    while (args.length) {
        var color = that.color_list.length;
        word_list = args.shift();
        if (!word_list.length) {
            args.shift();
            continue;
        }
        that.color_list.push(args.shift());
        for (var i in word_list) {
            addWord(word_list[i],color);
        }
    }
    buildFailIndex();
    //console.log(that.root);
    return {
        render: function(content){
            if (!that.color_list.length) {
                return content;
            }
            var range_list = [];
            var p = that.root;
            var len = content.length;
            var _content = content.toLowerCase();
            for (var i = 0,val,temp; i < len; i++) {
                val = _content[i];
                while (p.next[val] === undefined && p != that.root) {
                    p = p.fail;
                }
                p = p.next[val] ? p.next[val] : that.root;
                temp = p;
                while (temp != that.root) {
                    if (temp.len) {
                        if (!range_list[temp.color]) {
                            range_list[temp.color] = [];
                        }
                        range_list[temp.color].push([i + 1 - temp.len, i + 1]);
                    }
                    temp = temp.fail;
                }
            }
            for (var color in range_list) {
                //console.log(range_list[color]);
                mergeRange(color,range_list[color]);
            }
            if (that.color_range === null) {
                return content;
            }
            var new_content = '',x = 0,y;
            for (y in that.color_range) {
                new_content += content.substring(x,y);
                x = that.color_range[y][0];
                new_content += '<b style="color:' + that.color_list[that.color_range[y][1]] + '">' + content.substring(y,x) + '</b>';
            }
            new_content += content.substring(x);
            that.color_range = null;
            return new_content;
        }
    }
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我們知道數據的存儲和檢索是兩個很重要的功能,當我們的數據量大了,怎麼能快速的檢索數據呢,答案是使用索引,可索引具體的技術實現有很多,選擇哪一種呢,我就以mysql為例記錄下它為什麼選擇了B+樹作為索引的實現方式。 1. 索引簡介 索引是一種用於快速查詢行的數據結構,就像一本書的目錄就是一個索引,如果 ...
  • 前言 本文將帶大家學習使用前端開發神器-charles,從基本的下載安裝到常見配置使用,為大家一一講解。 一、花式誇獎Charles 截取 Http 和 Https 網路封包。 支持重髮網絡請求,方便後端調試。 支持修改網路請求參數。 支持網路請求的截獲並動態修改。 支持模擬慢速網路。 好,騎上我心 ...
  • 一、堆和棧,數據的存儲方式 1.註意點: JS中是沒有堆和棧的概念,我們用堆和棧來講解,目的就是方柏霓講解,存儲方式是一致的。 2.存儲方式: 基礎數據類型進行值傳遞,複雜數據類型進行地址傳遞 <script> //1.基本數據類型 var str1 = "xiaoliao"; var str2 = ...
  • Web 創建設計 設計一個網站,需要認真思考和規劃。 最重要的是要知道你的訪問用戶。 用戶是瀏覽者 一個典型的訪問者將無法讀取您的網頁的全部內容! 無論您在網頁中發佈了多麼有用的信息,一個訪問者在決定是否繼續閱讀之前僅僅會花幾秒鐘的時間進行瀏覽。 請確保使你的觀點,在頁面的第一句!另外,您還需要在整 ...
  • powertools可以稱得上插件界的瑞士軍刀。 相對於VS Code中大多數插件的出現為瞭解決某一項弊端和不足,powertools則聚合了很多強大且實用的功能,能夠增強VS Code的功能,並提升VS Code的使用體驗。 powertools就如同之前使用iOS系統時使用過的一款軟體Workf ...
  • CommonJS 和 ES6 Module 究竟有什麼區別? 作為前端開發者,你是否也曾有過疑惑,為什麼可以代碼中可以直接使用 require 方法載入模塊,為什麼載入第三方包的時候 Node 會知道選擇哪個文件作為入口,以及常被問到的,為什麼 ES6 Module export 基礎數據類型的時候 ...
  • 在 Node.js 項目開發過程中,隨著項目的發展,調用關係越來越複雜,調試工具的重要性日益凸顯。 Node(v6.3+)集成了方便好用 V8 Inspect 調試器,允許我們通過 Chrome DevTools 進行圖形化的調試和性能分析。同時,我們也可以使用 VS Code,Webstorm 等 ...
  • 歡迎使用慕課網 - Markdown 編輯器 Markdown 編輯器使用一套簡單實用的標記語言來實現簡單的文本排版,可以讓你專註於鍵盤碼字而非排版,化繁為簡,回歸寫作本質,帶來前所未有的書寫體驗! 我們在工具欄提供了豐富的快捷鍵,可以使用它們標記不同的標題,將一些文字標記為粗體或者斜體,也可以創建 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...