mizusame

【Blogger】投稿・ページの文字数カウンターを設置する

ブログを書いていると、書いた文章の文字数を確認したくなることがあります。しかし、Blogger の投稿エディタには文字数を表示する機能がありません。

そこで今回は、Blogger に投稿・ページの文字数カウンターを設置する方法を紹介します。

アイキャッチ

Blogger に文字数カウンターを設置する方法

記事タイトルと本文の文字数をカウントし、Blogger のプレビューに表示する機能を実装していきます。

記事タイトル <data:post.title/>post-title、記事の本文 <data:post.body/>post-body というクラス名の要素で囲まれていると仮定して説明します。実際に導入する際は、お使いのテーマに合わせてコード内のクラス名も適宜変更してください。

記事全体の文字数をカウントするものと、記事内の段落 p の文字数をカウントするものの2種類のコードを考えました。

CSS は共通です。カウンターがページの右上に固定表示され、デフォルトで邪魔にならないよう薄く表示し、マウスホバーやタップしたときに濃くなるようにしています。

記事全体の文字数をカウントする

記事タイトルと本文の文字数、本文から改行や空白を除いた文字数をカウントします。

以下のコードを Blogger のテーマ編集画面の </body> の直前に貼り付け、テーマを保存してください。

<b:if cond='data:view.isPreview and data:view.isSingleItem'>
<script>//<![CDATA[
window.addEventListener('load', () => {
  const p_title = document.querySelector('.post-title');
  const p_body = document.querySelector('.post-body');
  
  if(!p_title || !p_body) return;
  
  const wrapper = document.createElement('ul');
  wrapper.className = 'word-count';
  wrapper.innerHTML = `
    <li>タイトル:${countGrapheme(p_title.innerText)} 文字</li>
    <li>本文(改行・空白含む):${countGrapheme(p_body.innerText)} 文字</li>
    <li>本文(改行・空白除く):${countGrapheme(p_body.innerText.replace(/\s+/g, ''))} 文字</li>
  `;
  
  document.body.append(wrapper);
});

function countGrapheme(string){
  const segmenter = new Intl.Segmenter('ja', {granularity: 'grapheme'});
  return [...segmenter.segment(string)].length;
}
//]]></script>
  
<style>/*<![CDATA[*/
.word-count {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 100;
  padding: 1em;
  line-height: 1.4;
  font-size: 1.2rem;
  background: #fff;
  color: #333;
  opacity: .2;
}
.word-count:hover {
  opacity: .8;
}
/*]]>*/</style>
</b:if>

本文には、見出しやコードブロック、引用なども含まれます。目次などの動的に追加される要素の文字数もカウントされるので、それらを含めたくない場合はコードの設置場所や実行タイミングなどに気を付ける必要があります。

今回、文字列を文や単語、書記素(見かけ上の1文字)などの単位に分割するための API Intl.Segmenter オブジェクトを用いて文字数をカウントしています。

一部の絵文字や異体字、難しめの漢字などを含む文字列に string.length を用いると、返ってくる数値と見かけ上の文字数が違うことがあり、正確に文字数を取得するためにはこの API が不可欠です。

ここらへんの詳細を知りたい方は以下の記事をお読みください。Intl.Segmenter の使い方もこちらを参考にしました。

段落のみの文字数をカウントする

記事タイトルと記事本文の段落 p タグのみの文字数、段落から改行や空白を除いた文字数をカウントします。

以下のコードを Blogger のテーマ編集画面の </body> の直前に貼り付け、テーマを保存してください。

<b:if cond='data:view.isPreview and data:view.isSingleItem'>
<script>//<![CDATA[
window.addEventListener('load', () => {
  const p_title = document.querySelector('.post-title');
  const p_para = document.querySelectorAll('.post-body p');
  
  if(!p_title || !p_para) return;
  
  let c_para = '';
  
  for(let i = 0; i < p_para.length; i++){
    c_para += p_para[i].innerText;
  }
  
  const wrapper = document.createElement('ul');
  wrapper.className = 'word-count';
  wrapper.innerHTML = `
    <li>タイトル:${countGrapheme(p_title.innerText)} 文字</li>
    <li>本文(改行・空白含む):${countGrapheme(c_para)} 文字</li>
    <li>本文(改行・空白除く):${countGrapheme(c_para.replace(/\s+/g, ''))} 文字</li>
  `;
  
  document.body.append(wrapper);
});

function countGrapheme(string){
  const segmenter = new Intl.Segmenter('ja', {granularity: 'grapheme'});
  return [...segmenter.segment(string)].length;
}
//]]></script>
  
<style>/*<![CDATA[*/
.word-count {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 100;
  padding: 1em;
  line-height: 1.4;
  font-size: 1.2rem;
  background: #fff;
  color: #333;
  opacity: .2;
}
.word-count:hover {
  opacity: .8;
}
/*]]>*/</style>
</b:if>

段落の文章は、記事本文 .post-body 内の p タグの内部テキストを対象にしています。

p が入れ子になっていると文字数が重複するんじゃないの?と思う方もいらっしゃるかもしれませんが、p には以下のような特徴があるため、そもそも入れ子になることはありません。

段落はブロックレベル要素であり、特徴的なのは </p> で閉じる前に他のブロックレベル要素が見つかった場合は自動的に閉じることです。

ただ、blockquote を親要素に持つ p などもカウントされてしまうので、.post-body 内の直下の子要素 p に限定したい場合は、セレクタの指定を .post-body > p にする必要があります。

あとがき

Blogger の投稿エディタには文字数を表示する機能がないため、投稿・ページのプレビューに文字数カウンターを表示する方法を紹介しました。

今まで文字数を取得するためになにも考えずに string.length を使っていたんですが、この記事を書くにあたって Intl.Segmenter オブジェクトのことを知れたので、これからこっちを積極的に使っていこうと思います。

Blogger の投稿やページの文字数が知りたい方は参考にしてみてください。

編集
ホーム