ホーム > カテゴリ > HTML5・JavaScript >

Google-Code-Prettifyのソースコピー問題の対応方法

google-code-prettifyでハイライト表示したソースコードをブラウザでコピーするとIE/FireFoxでは正常にコピーする事が出来ない場合があります。そのコピー問題を解決する方法です。(google-code-prettify側は一切、修正しません。)

prettify_plus.jsを使用する

私がこのブログのシステムを作成する時に作ったJavaScriptです。

[prettify_plus.js]

  // 特殊なHTMLエンティティを文字に戻す
  // ※他にも追加したい場合は追記して下さい
  function htmlspecialchars_decode(text) {
    var result = text;
    result = result.replace(/&lt;/g   , '<');
    result = result.replace(/&gt;/g   , '>');
    result = result.replace(/&quot;/g , '"');
    result = result.replace(/&#39;/g  , "'");
    result = result.replace(/&#039;/g , "'");                   
    result = result.replace(/&apos;/g , "'");    
    result = result.replace(/&nbsp;/g , " ");        
    return result.replace(/&amp;/g    , '&');
  } 
    
  // 装飾後の<pre>内の中身からタグを除去
  function remove_tag(text,newline_count){
    
    var result        = ""; 
    var target_tag    = "";  
    var lessthan_flg  = false;        
    var list = text.split(''); 
    
    newline_count[0]  = 0;
    
    for(i=0;i<list.length;i++){
     
      // 開始タグ
      if (list[i] == '<') {
        lessthan_flg = true;
        target_tag   = list[i];
        continue;
      }

      // 終了タグ
      if (list[i] == '>') {
        lessthan_flg = false;
        target_tag = target_tag +list[i];
        if (target_tag == '</li>' || target_tag == '</LI>'){
            result = result +  "\r\n"; // CRLF :-)
            newline_count[0]++;
        }
        continue;
      }
      
      // タグ以外の文字を取得
      if (!lessthan_flg){ 
        result = result + list[i];
      }else{
        target_tag = target_tag +list[i];
      }
    }
    return result;
  }
 
  // RAWエレメントの生成(textarea)
  function createRawElement(raw,parent_obj,pre_obj,newline_count) {
      var element = document.createElement('textarea'); 
      
      element.id             = pre_obj.id + "_raw"; 
      element.rows           = newline_count+2; 
      element.readOnly       = true;    
      
      // IE8以下の場合はinnerHTMLで設定すると改行が除去される
      // element.innerHTML   = raw; 
      element.value          = raw;    
      
      parent_obj.appendChild(element); 
  } 
 
  // RAWエレメントの非表示
  function hiddenRawElement(parent_obj,msg_obj,pre_obj) {   
    pre_obj.style.display= "block";  
    document.getElementById(pre_obj.id + "_raw").style.display = "none";
    msg_obj.innerHTML='<a href="#" onclick="showRawElement(' + parent_obj.id + ',' + msg_obj.id  + ',' + pre_obj.id + '); ' +
                                           'return false;"  style="font-size:14px;">ソースをコピー</a>';
  }  
   
  // RAWデータの表示
  // parent_obj: 親オブジェクト(<pre>の上位)
  // msg_obj   : msgオブジェクト(コードの切り替え)
  // pre_obj   : <pre>オブジェクト
  function showRawElement(parent_obj,msg_obj,pre_obj){
    
    if (!document.getElementById(pre_obj.id + "_raw")) {
      
      // RAWデータの生成 
      // (IE8以下のinnerHTMLを経由すると改行が抹消されるので注意)
      var newline_count = new Array(0);
      var raw = remove_tag(pre_obj.innerHTML,newline_count);   
   
      // RAWデータの特殊なHTMLエンティティの解除
      raw = htmlspecialchars_decode(raw);

      // RAWエレメントの生成(textarea)
      createRawElement(raw,parent_obj,pre_obj,newline_count[0]); 
    }else{
      document.getElementById(pre_obj.id + "_raw").style.display = "block";
    }
   
    // 装飾済みのエレメント(pre)を非表示
    pre_obj.style.display= "none";      
                  
    msg_obj.innerHTML='<a href="#" onclick="hiddenRawElement(' + parent_obj.id + ',' + msg_obj.id  +  ',' + pre_obj.id + '); ' + 
                                           'return false;"  style="font-size:14px;">元に戻す</a><p></p>';
  }

[CSS]

.com { color: #080; }  /* コメント */
.str { color: #800  }  /* 文字列   */
.typ { color: #000; }  /* タイプ、クラス名等  */
.kwd { color: #0068b7; font-weight:bold; } /* キーワード */

pre.prettyprint {
  background-color: #fff;
  font-family:"メイリオ", Meiryo,Verdana, Helvetica, sans-serif;
  font-size:14px;
  overflow:auto;    
  max-height: 500px !important;  
}    

ol.linenums{
  padding-left: 46px !important;
}

ol.linenums li {
  list-style: decimal outside;
  border-left: solid 3px #6CE26C;
  padding-left: 10px;
  background-color: #fff;
}

textarea{
    width : 98%;
    font-family:"メイリオ", Meiryo,Verdana, Helvetica, sans-serif;
    font-size:14px;
    border-radius: 4px;
    overflow:auto;
    background-color: #fff;
    padding-left: 10px;
    margin-bottom: 15px;;
    max-height: 500px !important;  
  }

使用方法

run_prettify.js、prettify_plus.js、CSSの順で読み込ませてください。

<head> 
  <script src="http://あなたの環境/run_prettify.js"></script>
  <script src="http://あなたの環境/prettify_plus.js"></script>
  <link rel="stylesheet" href="http://あなたの環境/xxx.css" type="text/css">
</head>
 
 ... 

<div id="src1" >
  <div id="msg1" style="text-align:right;padding-right:10px;">
    <a href="#" onclick="showRawElement(src1,msg1,pre1);return false;" style="font-size:14px;">ソースをコピー</a>
  </div>
  <pre class="prettyprint linenums" id="pre1">
   ここにソースを記述
  </pre>
</div>

※ID/スタイルは適宜変更してください。
※IDは自動で採番や日付を付与すると複数に対応しやすいです。例) src1,src_2014_1224_1200など

利用条件

商用・非商用を問わずにご利用できます。但し、必ずダウンロードしてあなたの環境に設置してください。また、改変や再配布に関してはお好きなだけどうぞ :-)





関連記事



公開日:2014年12月17日 最終更新日:2015年12月21日
記事NO:00030