読者です 読者をやめる 読者になる 読者になる

Corredor

ウェブ、プログラミングの勉強メモ。

はてなブログのトップページやアーカイブページで記事ごとにシェアリンクを追加する

はてなブログ JavaScript Minify Uglify

はてなブログ標準のシェアリンク (ソーシャルパーツとも) は、通常だと各記事のページにしか表示されない。これを、トップページや、月別・カテゴリ別・検索結果などのアーカイブページにおいて、各記事の下にシェアリンクを追加する方法を紹介する。

完成形としては、以下の画像のように、各記事の下部に独自シェアリンクが配置された状態になる。

f:id:neos21:20170212215056p:plain

通常のソーシャルパーツや独自シェアリンク

通常のシェアリンクは、「デザイン」→「カスタマイズ」→「記事」より、「ソーシャルパーツ」を選択して任意のシェアリンクを追加できる。

これを独自のシェアリンクにして高速化を図る方法は、以下の記事で紹介したように、「デザイン」→「カスタマイズ」→「記事」→「記事下」に HTML を追加することで作成できる。付随する CSS も以下で紹介しているので、シェアリンクのデザインは以下の記事をドウゾ。

neos21.hatenablog.com

このブログの場合、「記事下」に以下のような HTML を追加している。{Permalink}{Title} 部分は、はてなブログが各記事の URL やタイトルに自動的に置換してくれる。

<ul class="neos21-share">
  <li class="neos21-share-hatebu"><a href="http://b.hatena.ne.jp/entry/{Permalink}"><i class="blogicon-bookmark"></i><span>Bookmark</span></a></li>
  <li class="neos21-share-twitter"><a href="https://twitter.com/share?url={Permalink}&amp;text={Title}"><i class="blogicon-twitter"></i><span>Twitter</span></a></li>
  <li class="neos21-share-facebook"><a href="http://www.facebook.com/share.php?u={Permalink}"><i class="blogicon-facebook"></i><span>Facebook</span></a></li>
  <li class="neos21-share-pocket"><a href="http://getpocket.com/edit?url={Permalink}&amp;title={Title}"><i class="blogicon-chevron-down"></i><span>Pocket</span></a></li>
</ul>

独自シェアリンクを記事ごとに置く方法

さて、このような独自のシェアリンクを、トップページやアーカイブページにおいて記事ごとに配置するには、JavaScript を組み合わせるしかない。つまり、以下のような方法を取る。

  1. 「フッタ」部分に、シェアリンクのテンプレートとなる HTML を置いておく
  2. ページ読み込み時に、1. で用意したテンプレート HTML を複製し、記事ごとに URL やタイトル部分を書き換えて DOM 挿入する

ということで、この方法を紹介する。

テンプレート HTML

シェアリンクのテンプレートとなる HTML は、以下のようなものになる。これを「デザイン」→「カスタマイズ」→「フッタ」に仕込んでおく

<!-- シェアリンクのテンプレート -->
<div id="neos21-template" style="display:none;">
  <ul class="neos21-share" id="neos21-share-template">
    <li class="neos21-share-hatebu"><a class="neos21-share-hatebu-link"><i class="blogicon-bookmark"></i><span>Bookmark</span></a></li>
    <li class="neos21-share-twitter"><a class="neos21-share-twitter-link"><i class="blogicon-twitter"></i><span>Twitter</span></a></li>
    <li class="neos21-share-facebook"><a class="neos21-share-facebook-link"><i class="blogicon-facebook"></i><span>Facebook</span></a></li>
    <li class="neos21-share-pocket"><a class="neos21-share-pocket-link"><i class="blogicon-chevron-down"></i><span>Pocket</span></a></li>
  </ul>
</div>

記事ごとに設置しているシェアリンクと同様のスタイルを適用させるため、基本的には「記事下」に配置した HTML と同様。一部異なるのは、いずれもスクリプトで処理するための部分。

  • テンプレートとして複製するときに扱いやすくするため、ul.neos21-share に対し #neos21-share-template という ID を付与している。
  • a 要素には href 属性を書いていない。記事ごとに URL を作る必要があるため、ココでは書いておかない。
  • その代わり、この a 要素を特定しやすくするため、記事ごとのシェアリンクには付けていなかった .neos21-share-【SNS 名】-link というクラス名を付与している。
  • このテンプレート全体は表示させる必要がないので、これを囲んだ div#neos21-template には display:none を書いておくと安全。

というワケで、このようなテンプレート HTML が完成する。

記事ごとにテンプレートを複製するスクリプト

このテンプレート HTML を複製し、記事ごとに仕込んでいくための処理は、以下のような JavaScript で行う。これも「デザイン」→「カスタマイズ」→「フッタ」に仕込んでおく。先程のテンプレート HTML の直後にでも置いておけば良いだろう。

<script>
  // 記事ごとにシェアリンクを追加する
  (function() {
    // Body 要素に任意のクラス名が存在するか確認する関数
    var hasClass = function(className) {
      return (" " + document.body.className + " ").replace(/[\n\t]/g, " ").indexOf(" " + className + " ") !== -1;
    }
    
    /// Body 要素のクラス名に応じて記事一覧を取得し、シェアリンクの挿入先を決定する
    var articles;
    var destClassName;
    if(hasClass("page-index")) {
      // トップページの場合
      articles = document.getElementsByClassName("hentry");
      destClassName = "customized-footer";
    }
    else if(hasClass("page-archive")) {
      // アーカイブページ (月別・カテゴリ別・検索結果) の場合
      articles = document.getElementsByClassName("archive-entry");
      destClassName = "archive-entry-body";
    }
    else {
      // 該当しないページでは処理しない (シェアリンクは作らない)
      return;
    }
    
    // ページが読み込まれたら実行する
    document.addEventListener("DOMContentLoaded", function() {
      // テンプレートを取得する
      var template = document.getElementById("neos21-share-template");
      template.removeAttribute("id");
      
      // 記事ごとにシェアリンクを複製して作っていく
      Array.prototype.forEach.call(articles, function(article) {
        // 記事情報を取得する。記事タイトルのみ URL 用にエンコードしておく
        var entryTitleLink = article.getElementsByClassName("entry-title-link")[0];
        var title = encodeURIComponent(entryTitleLink.innerText);
        var permalink = entryTitleLink.getAttribute("href");
        
        // テンプレートを複製する
        var clone = template.cloneNode(true);
        
        // はてブ用リンク:http://b.hatena.ne.jp/entry/{Permalink}
        var hatebuLink = clone.getElementsByClassName("neos21-share-hatebu-link")[0];
        hatebuLink.setAttribute("href", "http://b.hatena.ne.jp/entry/" + permalink);
        
        // Twitter 用リンク:https://twitter.com/share?url={Permalink}&amp;text={Title}
        var twitterLink = clone.getElementsByClassName("neos21-share-twitter-link")[0];
        twitterLink.setAttribute("href", "https://twitter.com/share?url=" + permalink + "&amp;text=" + title);
        
        // Facebook 用リンク:http://www.facebook.com/share.php?u={Permalink}
        var facebookLink = clone.getElementsByClassName("neos21-share-facebook-link")[0];
        facebookLink.setAttribute("href", "http://www.facebook.com/share.php?u=" + permalink);
        
        // Pocket 用リンク:http://getpocket.com/edit?url={Permalink}&amp;title={Title}
        var pocketLink = clone.getElementsByClassName("neos21-share-pocket-link")[0];
        pocketLink.setAttribute("href", "http://getpocket.com/edit?url=" + permalink + "&amp;title=" + title);
        
        // 記事下部に挿入する
        article.getElementsByClassName(destClassName)[0].appendChild(clone);
      });
      
      // テンプレートを削除する
      document.getElementById("neos21-template").removeChild(template);
    }, false);
  })();
</script>

少々長いが、コメントも付けているので、やろうとしていることは分かっていただけるかと思う。

  • まずは Body 要素のクラス名から、このページが「トップページ」か「アーカイブページ」かを判別する。
    • それ以外のページ (プロフィールページや各記事のページ) はシェアリンクが不要なので、return; で処理しないようにしている。
    • 「トップページ」の場合と「アーカイブページ」の場合とで、記事ごとの HTML が若干異なる。
      • トップページ (body.page-index) の場合 : article.hentry の数だけ記事が存在する。各記事のフッタには空の div.customized-footer が存在するので、この内にシェアリンクを追加していく。
      • アーカイブページ (body.page-archive) の場合 : section.archive-entry の数だけ記事が存在する。各記事にフッタを示す要素はないので、本文とはてなスターが含まれている、div.archive-entry-body の最後に追加していく。
  • ココからの処理は、トップページかアーカイブページのいずれかの場合のみ行われる。document.addEventListener("DOMContentLoaded") を利用して、ページ読み込み時に使用する。
  • 最初に置いたテンプレート HTML のうち、ul#neos21-share-template を変数 template として取得しておく。これを記事ごとに複製して加工していく。複製時に邪魔しないよう ID は消しておく。
  • 記事ごとのループ処理は Array.prototype.forEach.call() を利用する。第一引数に Array ライクな関数、つまりココでは var articles が記事の要素の配列になっているので、コレを指定する。第二引数が配列の各要素に行わせる処理を関数で書いておく。この関数の引数 (ココでは article 部分) が、各要素を示す変数になる。ということで、Array.prototype.forEach.call(articles, function(article) {}); という枠組みができる。

ループ処理の中では、テンプレート HTML を複製して加工していく。

  • シェアリンクを作るため、「記事ごとの URL」と「記事のタイトル」を取得する。これは、記事タイトルとそのリンクが h1.entry-title > a.entry-title-linkでマークアップされているので、このa.entry-title-link` を拾ってやればいい。
  • a.entry-title-linkhref 属性値はどうもエスケープされた URL が入っているようなので、変数 permalink には #encodeURIComponent() は噛ませない。
  • 記事のタイトルは a.entry-title-link.innerText で取得する。リンク URL に組み込むため、#encodeURIComponent() でエスケープしておく。
  • 変数 template を、#cloneNode(true) で子要素含めて丸ごと複製する。この複製した変数 clone の HTML をアレコレいじくって、記事の下部に挿入していく。
  • 各 SNS に合わせたリンク URL を生成していく。変数 clone の中から、各 a 要素を取得する。これを楽に書くため、a 要素に .neos21-share-【SNS 名】-link というクラス名を付与していた。
  • この a 要素に href 属性を設定する。ココは各記事用のシェアリンクと同様なのだが、はてなブログが用意していた {Permalink}{Title} といった変数ではなく、先ほどこねこね作った permalinktitle という変数を使うことになる。
  • こうして、変数 clone の中は各記事のシェアリンクに書き換えられた。あとはこれを各記事の最下部に挿入する。ページを判別したときに控えておいた destClassName が挿入先のノードになるので、このノードに対して #appendChild() してやる。

最後に仕上げ。

  • テンプレート全体を囲んでいる div#neos21-template には display:none を指定しているので、必ずしもやる必要はないが、元の ul#neos21-share-template#removeChild() で消しておくと気持ち良いかも。

これでやりたいことはできた。

アーカイブページのためにスタイルを少し直す

アーカイブページにおいて、サムネイル付きの記事の場合にシェアリンクが崩れるのを確認したので、Float を解除するための Clearfix を仕込んでおくと良いだろう。アーカイブページであることを判別するには、JavaScript でやっているのと同様、Body 要素に .page-archive クラスが付与されていれば良いので、これを親セレクタとして指定してやる。

JavaScript で挿入する ul.neos21-share は、この span.social-buttons の後ろに入るので、span.social-buttons 内の span.star-container をブロック要素化してマージンを与えておく。

/* はてなスターが入っている span 要素の手前で Clearfix */
body.page-archive span.social-buttons:before {
  display:block;
  visibility:hidden;
  clear:both;
  height:0;
  font-size:0;
  content:".";
}

/* サムネイルとの余白を適度に開けるための指定 */
body.page-archive span.social-buttons span.star-container {
  display:block;
  margin-top:10px;
  margin-bottom:10px;
}

上記 CSS は HTML 構造を分かりやすくするために要素名も書いておいたが、余計なセレクタをかませると速度が遅くなるので、クラス名だけで良いだろう。

スクリプトを圧縮する

CSS の圧縮は以下の記事で説明したように、npm-scripts を利用した Minify の手法を用意してあるので、コチラをドウゾ。

neos21.hatenablog.com

JavaScript の方は、独自のクラス名部分が使い回せそうだったので、今回は人力で「オレオレ Uglify」をしてみた。

!function(){var d=document,i="getElementById",c="getElementsByClassName",q="setAttribute",f="href",s=" ",h=function(C){return ~(s+d.body.className+s).replace(/[\n\t]/g,s).indexOf(s+"page-"+C+s)},a,e,n="neos21-",r="share-",w=n+r,l="-link",t="template";if(h("index"))a=d[c]("hentry"),e="customized-footer";else{if(!h("archive"))return;a=d[c]("archive-entry"),e="archive-entry-body"}d.addEventListener("DOMContentLoaded",function(){var T=d[i](w+t);T.removeAttribute("id");Array.prototype.forEach.call(a,function(A){var L=A[c]("entry-title"+l)[0],E=encodeURIComponent(L.innerText),P=L.getAttribute(f),o=T.cloneNode(1),x=function(N,U){o[c](w+N+l)[0][q](f,U)};x("hatebu","http://b.hatena.ne.jp/entry/"+P);x("twitter","https://twitter.com/share?url="+P+"&amp;text="+E);x("facebook","http://www.facebook.com/share.php?u="+P);x("pocket","http://getpocket.com/edit?url="+P+"&amp;title="+E);A[c](e)[0].appendChild(o)});d[i](n+t).removeChild(T)},0)}()

このコードは先ほどのスクリプトと完全に同じ動きをする。

少しだけ改行を入れ、コメントを追加してみよう。

// !function(){}(); で即時関数になる
!function(){
  var d=document,
      i="getElementById",
      c="getElementsByClassName",
      q="setAttribute",
      f="href",
      // Body 要素のクラスを判別する関数
      s=" ",
      h=function(C){
        // ~ 演算子を使うと「indexOf() !== -1」(>= も同義) を代用できる
        return ~(s+d.body.className+s).replace(/[\n\t]/g,s).indexOf(s+"page-"+C+s)
      },
      // a : 元のコードの変数 articles に相当
      a,
      // e : 元のコードの変数 destClassName に相当
      e,
      // 使い回せそうなクラス名の文字列を分解して保持しておく
      n="neos21-",
      r="share-",
      // "neos21-share-"
      w=n+r,
      l="-link",
      t="template";
  
  // 頻繁に使う document.getElementsByClassName() などはブラケット記法 (配列記法) でアクセスする
  // カンマ演算子を利用して処理
  if(h("index")) a=d[c]("hentry"), e="customized-footer";
  else{
    // return を先に行わせれば if 文を1行で済ませられる
    if(!h("archive"))return;
    a=d[c]("archive-entry"),e="archive-entry-body"
  }
  
  d.addEventListener("DOMContentLoaded",function(){
    // テンプレート取得
    var T=d[i](w+t);
    T.removeAttribute("id");
    
    Array.prototype.forEach.call(a,function(A){
      // 変数 A が各記事の要素、変数 L が記事タイトルのリンク要素を取得
      var L=A[c]("entry-title"+l)[0],
          // E : title
          E=encodeURIComponent(L.innerText),
          // P : permalink
          P=L.getAttribute(f),
          // o : 複製した要素 (clone)。「1」は暗黙型変換で「true」。
          o=T.cloneNode(1),
          // x : 指定クラスの href 属性に指定の URL 文字列を設定する、という処理を関数化
          x=function(N,U){
            o[c](w+N+l)[0][q](f,U)
          };
      // リンクの加工
      x("hatebu","http://b.hatena.ne.jp/entry/"+P);
      x("twitter","https://twitter.com/share?url="+P+"&amp;text="+E);
      x("facebook","http://www.facebook.com/share.php?u="+P);
      x("pocket","http://getpocket.com/edit?url="+P+"&amp;title="+E);
      // 記事下部に追加
      A[c](e)[0].appendChild(o)
    });
    
    // テンプレート削除
    d[i](n+t).removeChild(T)
  },0)
  // false は暗黙型変換を利用して 0 と表記
}()

こんな感じ。"entry" という文字列も4回出てきているのだが、1文字変数を作って文字列連結しても1文字多くなってしまうので止めた。

というか、はてブロテンプレートのクラス名を1文字変数で作るのは乱暴過ぎる気がするので、"page-“ を関数内に埋め込んだり、.entry-title-link に変数を使ったりするのは止めた方が良いとは思う。可読性も兼ねて人力圧縮するなら、文字列結合で別の動きをさせるのは避けた方が良いだろう。

そういうワケで、このブログの最終的な「フッタ」HTML には、以下のように HTML と JavaScript を圧縮して挿入している。

<div id="neos21-template"><ul class="neos21-share" id="neos21-share-template"><li class="neos21-share-hatebu"><a class="neos21-share-hatebu-link"><i class="blogicon-bookmark"></i><span>Bookmark</span></a></li><li class="neos21-share-twitter"><a class="neos21-share-twitter-link"><i class="blogicon-twitter"></i><span>Twitter</span></a></li><li class="neos21-share-facebook"><a class="neos21-share-facebook-link"><i class="blogicon-facebook"></i><span>Facebook</span></a></li><li class="neos21-share-pocket"><a class="neos21-share-pocket-link"><i class="blogicon-chevron-down"></i><span>Pocket</span></a></li></ul></div>
<script>!function(){var d=document,i="getElementById",c="getElementsByClassName",q="setAttribute",f="href",s=" ",h=function(C){return ~(s+d.body.className+s).replace(/[\n\t]/g,s).indexOf(s+"page-"+C+s)},a,e,n="neos21-",r="share-",w=n+r,l="-link",t="template";if(h("index"))a=d[c]("hentry"),e="customized-footer";else{if(!h("archive"))return;a=d[c]("archive-entry"),e="archive-entry-body"}d.addEventListener("DOMContentLoaded",function(){var T=d[i](w+t);T.removeAttribute("id");Array.prototype.forEach.call(a,function(A){var L=A[c]("entry-title"+l)[0],E=encodeURIComponent(L.innerText),P=L.getAttribute(f),o=T.cloneNode(1),x=function(N,U){o[c](w+N+l)[0][q](f,U)};x("hatebu","http://b.hatena.ne.jp/entry/"+P);x("twitter","https://twitter.com/share?url="+P+"&amp;text="+E);x("facebook","http://www.facebook.com/share.php?u="+P);x("pocket","http://getpocket.com/edit?url="+P+"&amp;title="+E);A[c](e)[0].appendChild(o)});d[i](n+t).removeChild(T)},0)}()</script>

これでトップページからも記事をシェアしてもらいやすくなったと思うので、皆様どうかシェアのほど宜しくお願い致します。w

.bash_profile と .bashrc は何が違うの?使い分けを覚える

Bash GitBash Linux ターミナル

普段 Windows で GitBash を起動して Bash しか使わない人とか、Mac OSX デフォルトのターミナルしか触らない人とかは、これらの違いやそれによる利便を感じることはないと言える。自分も今のところ、「分かれていることで便利だ」と感じるようなことはない。

ただ、世間一般的にどういう風に捉えられているのか、自分はどう使い分けておくといいのかを整理しておこう。

動きを整理する

まずは .bash_profile.bashrc の中身を以下のようにしてみることで、それぞれのファイルの動きを整理してみよう。

# .bash_profile
echo This is .bash_profile
# .bashrc を読み込む
test -r ~/.bashrc && . ~/.bashrc
# .bashrc
echo This is .bashrc

このような状態で、例えば GitBash を、例えばターミナル.app を起動してみる。するとどうなるか。

This is .bash_profile
This is .bashrc
$

このように、.bash_profile.bashrc を読み込もうとしているので、このように実行されている。ちなみに、.bash_profile 内に .bashrc を読み込むコマンドを書かないと、.bashrc は読み込まれない。

ではターミナルを起動後、bash コマンドで新たに Bash を起動したらどうなるか。

$ bash
This is .bashrc
$

今度は .bash_profile は読み込まれておらず、.bashrc だけが読み込まれていることが分かる。

よく云われている、

  • .bash_profile はログイン時に1回だけ実行される
  • .bashrc はシェルを起動するたびに実行される

とはこういう動作のことを指している。

だから、例えば GUI 環境を持つ Linux マシンにログインして、画面上からターミナルを起動すると、.bash_profile は実行されず、.bashrc だけが実行される。Linux に既にログインしているからだ。

.bash_profile はログイン時に1回だけ実行される

さて、じゃあ .bash_profile には何を書くのが良いのだろうか。答えは、環境変数を書くものとして扱うのが良い。

環境変数とは、export コマンドで宣言する変数だ。この環境変数はプロセス間で共有されるので、シェルを起動するたびに何度も呼ぶ必要がない。

だから、.bash_profile は環境変数を書いたら、さっさと .bashrc を読み込んで終わらせてしまうだけの、普段はあんまりカスタマイズしないところとしておくと良いだろう。

.bashrc はシェルを起動するたびに実行される

一方、.bashrc はシェルを起動するたびに実行されるので、環境変数ではない変数だとか、エイリアスとか、独自のシェル関数を宣言しておくと良い。

.bash_profilealias コマンドでエイリアスを登録してしまうと、ターミナルを起動後に bash コマンドで新たなシェルを起動したときに、.bash_profile に書いた alias は読み込まれない。エイリアスは .bashrc に書いた方が良い。

エイリアスなら、環境変数よりは色々弄る機会が多いと思うので、「普段は .bashrc に書く」と覚えてしまって良いだろう。

参考

コマンドプロンプトでビープ音を鳴らす

Windows コマンド Windows バッチ

2ch で見つけたネタ。

884 : デフォルトの名無しさん[sage] 投稿日:2017/01/27(金) 21:16:38.29 id:ss8+Q0ea.net
こういうのもここで覚えたよ
for /f “delims=0” %%I in (‘cmd /u /c echo 〇’) do set BEL=%%I
echo %BEL%

BEL 文字でビープ音が鳴らせる

元々、コマンドプロンプト上でアスキーコード「7」の「BEL 文字」を Echo すると、コマンドプロンプトからビープ音が鳴らせるということは知っていた。

Rem 「^G」はコマンドプロンプト上で「Ctrl + G」とキー押下すると入力できる
Echo ^G

この「BEL」「^G」とは、制御文字の一つで、その名のとおり、この文字を受け取った端末のベル (ビープ音) を鳴らす特殊な文字なのである。制御文字というと、ターミナルで Backspace を打って ^H という文字が出てくるのを見かけたり、得体の知れないシェルスクリプトを Vim で開いたときに行末に ^M が付いているのを見かけることがあるかもしれない。これらはそれぞれ、「後退」「キャリッジリターン」を意味していて、キャリッジリターンは \r というエスケープシーケンスや CR という略号でも知られているであろう。

BEL 文字をどうやってバッチファイルに書き込むか

コマンドプロンプト上の「^G」というこの表示は、Ctrl + G というキー操作で入力されたアスキーコード「7」を、「^G」というキャレット記法で表現しているものである。

従って、「キャレット」「G」という2文字を入力してもビープ音は鳴らせない。

そのため、ベルを鳴らすバッチファイルを書こうとすると、少々厄介だ。

まず、Windows 標準の「メモ帳」だと、制御文字を表示したり挿入したりできないのである。

個人的に使用している「Notepad++」なら、「制御文字の表示」というオプションがあるので、「文字コード表」から BEL 文字を入力してそれを閲覧できたりするが、エディタを用意して表示設定を変えて制御文字を入力する、と、少々面倒だったりする。また、こうして書いたバッチファイルを「メモ帳」で開くと、「^G」などの表示はされないので、BEL 文字が入力されているのかどうかやはり判別できないのである。

そこで Unicode

そこでようやく冒頭のコードだ。

少し改変して、コマンドプロンプト上で直接入力できるようにしたものを以下に置いておく。

For /f "delims=0" %a In ('Cmd /u /c Echo 〇') Do @Echo %a

これを実行すると、ビープ音が鳴る。

コード中に制御文字が隠れているワケではない。キモなのは、コード中にある漢数字のゼロ「〇」だ。

これは「まる」で変換して出せる円記号「○」(U+25CB) ではなく、「ぜろ」で変換して出せる漢数字の零「」(U+3007) である。

んで、これを For 内にある Cmd コマンドを挟んで Echo しているのだが、Cmd コマンドのスイッチ (オプション) に /u というものが付いている。

Cmd /u とすると、コマンドの実行結果を Unicode 形式で返却してくれる。デフォルトは ANSI で、/a スイッチを指定したのと同義なのだが、/u とすることで Unicode にできる。

この機能を利用し、漢数字の零を Unicode 形式にして返却させることで、For 文の変数 %a にはベル文字が入るということになるのである。そしたらそれを @Echo してやることで、ビープ音が鳴らせるという寸法だ。

冒頭のコードは、バッチファイル内で変数 BEL にベル文字を入れていることになる。