正規表現で OR 検索したやつを別々の色でハイライト

  • /*
     * @title 正規表現で OR 検索したやつを別々の色でハイライト
     * @description 正規表現で OR 検索したやつを別々の色でハイライト
     * @license MIT License
     * @javascript_url
     */
    
    const REGEXP = new RegExp(prompt('RegExp'), 'ig')
    
    const getAllTextNodes = (cb) => {
      const walker = document.createTreeWalker(
        document.body,
        NodeFilter.SHOW_TEXT, // テキストノードだけを考慮
        null,
        false
      );
      let node;
      while ((node = walker.nextNode())) {
        if (node.textContent.trim() !== '')
          cb(node)
      }
    };
    
    const createElementFromString = (htmlString) => {
      const div = document.createElement('div');
      div.innerHTML = htmlString;
      return div.firstChild;
    };
    
    const colors = ['yellow', 'yellowgreen', 'pink', 'orange', ];
    const matched = new Map();
    
    let lastIndex = -1;
    getAllTextNodes((node) => {
      const innerHTML = node.textContent.replace(REGEXP, (str) => {
        const key = str.toLowerCase()
        if (matched.has(key)) {
          const color = matched.get(key);
          return `<span style="padding: 1px; color: black; background-color: ${color};">${str}</span>`
        }
        const nextColor = colors[++lastIndex];
        matched.set(key, nextColor);
        return `<span style="padding: 1px; color: black; background-color: ${nextColor};">${str}</span>`;
      });
    
      const replacementNode = document.createElement('span');
      replacementNode.innerHTML = innerHTML;
      node.parentNode.insertBefore(replacementNode, node);
      setTimeout(() => node.parentNode.removeChild(node)); // 非同期じゃないと何故かエラーに...
    });
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。