JavaScript 銘柄コードでリンク

投稿者:
document.addEventListener("DOMContentLoaded", function () {
  const target = document.getElementById("body"); // PukiWiki本文
  if (!target) return;

  const walker = document.createTreeWalker(
    target,
    NodeFilter.SHOW_TEXT,
    {
      acceptNode: function (node) {
        if (
          node.parentNode &&
          ['SCRIPT', 'STYLE', 'A'].includes(node.parentNode.nodeName)
        ) {
          return NodeFilter.FILTER_REJECT;
        }
        return NodeFilter.FILTER_ACCEPT;
      }
    }
  );

  const regex = /([a-zA-Z0-9]{4})/g;
  const nodesToReplace = [];

  let node;
  while ((node = walker.nextNode())) {
    if (regex.test(node.nodeValue)) {
      nodesToReplace.push(node);
    }
  }

  for (const node of nodesToReplace) {
    const text = node.nodeValue;
    const frag = document.createDocumentFragment();
    let lastIndex = 0;

    text.replace(regex, (match, code, index) => {
      frag.appendChild(document.createTextNode(text.slice(lastIndex, index)));

      const before = text[index - 1];
      const after = text[index + 4];
      const isValidSurrounding =
        (!before || !/[a-zA-Z0-9]/.test(before)) &&
        (!after || !/[a-zA-Z0-9]/.test(after));

      const isNotAllLetters = !/^[a-zA-Z]{4}$/.test(code); // ← ここで全英字かチェック

      if (isValidSurrounding && isNotAllLetters) {
        const a = document.createElement("a");
        a.href = `https://finance.yahoo.co.jp/quote/${code}.T`;
        a.textContent = code;
        a.target = "_blank";
        a.rel = "noopener noreferrer";
        frag.appendChild(a);
      } else {
        frag.appendChild(document.createTextNode(code));
      }

      lastIndex = index + 4;
    });

    frag.appendChild(document.createTextNode(text.slice(lastIndex)));
    node.parentNode.replaceChild(frag, node);
  }
});

Thank you for reading this post, don't forget to subscribe!