※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);