【Charm.js拡張機能】「通常変換プレースホルダー置換」の使い方

Charm.js

※2024/07/22 置換処理を改良し、セキュリティリスクを低減しました。

この記事は、名前変換スクリプトCharm.jsの拡張機能の解説です。

カスタム変換(カタカナ変換、区切り等)とは別の説明となっておりますので、ご注意ください。
カスタム変換の説明はこちら(本館サイト)

拡張機能の導入方法についてはこちらの記事をご確認ください。

本館サイトでの拡張機能説明はこちら

通常変換プレースホルダー置換について

機能概要

通常変換でspanタグを使わずに、#charmname1#という書き方できるようになります。

注意・補足

  • 拡張機能のコード内でデフォルトネームを設定する必要があります。
  • カスタム変換には対応していません。
  • かなりのレアケースですが、JavaScriptが動かない場合は#charmname1#のように表示されます。
  • 各ページでデフォルトネームを変えたいときは、ページごとに拡張機能を用意する必要があります。
  • 今まで通りのspanタグももちろん使えます。

編集が必要なところ

replacementsに、名前のidとデフォルトネームを設定します。
書き方は元のコードを真似してください。

置換対象のタグはtargetTagsに追加できます。

拡張機能コード全体


/**
 * 通常変換プレースホルダー置換
 * #登録id#で書いたプレースホルダーをspanタグに置換する
 */
class BeforeSpanReplacer {
  // 登録idとデフォルトネーム
  static replacements = {
    'charmname1': '苗字',
    'charmname2': 'みょうじ',
    'charmname3': '名前',
    'charmname4': 'なまえ',
  };

  // 置換対象のタグリスト
  static targetTags = [
    'p', 'ruby', 'rt', 'h1', 'h2', 'h3', 'h4', 'h5', 'li', 'th', 'td', 'a', 'span', 'div'
  ];

  /**
   * 置換処理を実行
   */
  static run = () => {
    this.replaceText();
  };

  /**
   * 指定されたタグ内のテキストを置換
   */
  static replaceText = () => {
    this.targetTags.forEach(tag => {
      const elements = document.querySelectorAll(tag);
      elements.forEach(elm => {
        this.replacePlaceholdersInElement(elm);
      });
    });
  };

  /**
   * 要素内のテキストノードのプレースホルダーを置換
   * @param {Element} element - 置換対象の要素
   */
  static replacePlaceholdersInElement = (element) => {
    const childNodes = Array.from(element.childNodes);
    childNodes.forEach(child => {
      if (child.nodeType === Node.TEXT_NODE) {
        const replacedNodes = this.createReplacementNodes(child.textContent);
        child.replaceWith(...replacedNodes);
      } else if (child.nodeType === Node.ELEMENT_NODE) {
        this.replacePlaceholdersInElement(child);
      }
    });
  };

  /**
   * テキスト中のプレースホルダーを置換して新しいノードを生成
   * @param {string} text - 置換対象のテキスト
   * @returns {Array} 置換後のノード配列
   */
  static createReplacementNodes = (text) => {
    const fragment = document.createDocumentFragment();
    const parts = text.split(new RegExp(`(#${Object.keys(this.replacements).join('#|#')}#)`));

    parts.forEach(part => {
      const key = part.replace(/#/g, '');
      if (this.replacements[key]) {
        const span = document.createElement('span');
        span.className = key;
        span.textContent = this.replacements[key];
        fragment.appendChild(span);
      } else {
        fragment.appendChild(document.createTextNode(part));
      }
    });
    return Array.from(fragment.childNodes);
  };
}

Charm.addExtension("BeforeSpanReplacer", BeforeSpanReplacer);

圧縮版はこちらです。
ファイル容量を削減する場合はこちらをご利用ください。

class BeforeSpanReplacer{static replacements={charmname1:"苗字",charmname2:"みょうじ",charmname3:"名前",charmname4:"なまえ"};static targetTags=["p","ruby","rt","h1","h2","h3","h4","h5","li","th","td","a","span","div"];static run=()=>{this.replaceText()};static replaceText=()=>{this.targetTags.forEach(e=>{let t=document.querySelectorAll(e);t.forEach(e=>{this.replacePlaceholdersInElement(e)})})};static replacePlaceholdersInElement=e=>{let t=Array.from(e.childNodes);t.forEach(e=>{if(e.nodeType===Node.TEXT_NODE){let t=this.createReplacementNodes(e.textContent);e.replaceWith(...t)}else e.nodeType===Node.ELEMENT_NODE&&this.replacePlaceholdersInElement(e)})};static createReplacementNodes=e=>{let t=document.createDocumentFragment(),a=e.split(RegExp(`(#${Object.keys(this.replacements).join("#|#")}#)`));return a.forEach(e=>{let a=e.replace(/#/g,"");if(this.replacements[a]){let l=document.createElement("span");l.className=a,l.textContent=this.replacements[a],t.appendChild(l)}else t.appendChild(document.createTextNode(e))}),Array.from(t.childNodes)}}Charm.addExtension("BeforeSpanReplacer",BeforeSpanReplacer);
タイトルとURLをコピーしました