モーリーのメモ

アプリ開発等(プログラミング、CG作成)、興味を持ったことを実践してまとめるブログです。

モーリーのメモ

googleドキュメントで、ソースコードのインデント設定とHTMLタグの作成!


記事を修正しました。

  • 2016.05.24:追記

 注意!:この記事のスクリプトでは、正しく処理できない場合が多々あります。参考程度として利用して下さい。
 記事を削除しようかと思いましたが、部分部分で参考になるソースコードもあるので、とりあえず残します。

  • 既知の問題
    • コード内に正規表現リテラルが含まれる場合、正しく処理できません。
    • コード内にすでに装飾用のhtmlタグが含まれる場合、正しく処理できません。



 googleドキュメントに、JavaScriptソースコードを貼り付けて
f:id:mmorley:20160514214248p:plain:w300
 ぽちっとすると
f:id:mmorley:20160514214704p:plain:w150
 指定した幅でインデントを設定し直したり、
f:id:mmorley:20160514215733p:plain:w300
 ぽちっとすると
f:id:mmorley:20160514215712p:plain:w150
 はてな用のHTMLタグを作成出来るようにします。
f:id:mmorley:20160514220716p:plain:w300
 記事に貼り付けるとこうなります。

setInputControl: function () {
var self = this;
// キーボードのイベントリスナーを追加
cc.eventManager.addListener({
event: cc.EventListener.KEYBOARD,
// キーを押したときに、対応する方向に加速度を設定します。
onKeyPressed: function(keyCode, event) {
switch(keyCode) {
case cc.KEY.a:
self.accLeft = true;
self.accRight = false;
break;
case cc.KEY.d:
self.accLeft = false;
self.accRight = true;
break;
}
}
}, self.node);
},
 
 作り方を説明します。

使用環境

 私が使用している環境です。

  • Mac OS X El Capitan Version 10.11.4
  • ブラウザ:Google Chrome Version 50.0.2661.102 (64-bit)

設定方法

 googleドキュメントは、無料で使えるオンラインの文書作成(ワードみたいな)アプリです。
 利用するにはgoogleアカウントが必要です。

1.googleドキュメントを開く

  1. 下記のリンクをクリック
    Google Docs: Free Online Document Editor | Google Workspace

2.新しいドキュメントを作成

  1. 画面右下の赤い『+』をクリック
    f:id:mmorley:20160511135546p:plain
    『無題のドキュメント』が開きます。
  2. 名前を変更
    名前は何でも構いません。
    f:id:mmorley:20160514221707p:plain:w500

3.スクリプトエディタを開く

  1. 『ツール』-『スクリプトエディタ』をクリック
    f:id:mmorley:20160514222050p:plain:w500
    スクリプトエディタで『無題のプロジェクト』が開きます。

4.コードをコピペする

  1. スクリプトエディタの『コード.gs』にあるコードを全て削除
  2. 下記のコードをコピーして、『コード.gs』に貼り付ける
function translate(indentFlg, tagFlg) {
  var doc = DocumentApp.getActiveDocument(); // アクティブドキュメント 
  var indentText = "    "; // デフォルトのインデントを設定
  var baseIndentCount = 0; // 通常行のインデント数を設定
  var addBaseIndentCount = 0;
  
  var text = doc.getText(); // 本文を取得
  var rows = text.split('\n');
  var row = "";
  var checkRow = "";
  var result = "";
  var startFlg = false;
  var propertiesFlg = false; // properties内のdefaultか確認用
  var propertiesIndentCount = 0;
  var arrSwitchIndentCount = [];
  var Count = 0;
  var metaText = "";

  for(var i = 0; i < rows.length; i++){  
    row = rows[i];
    if(indentFlg) {
      row = row.replace(/^\s+/, ""); // 先頭の半角を除去
      row = row.replace(/^\t+/, ""); // 先頭のタブを除去
      
      // コメント等除外
      checkRow = row.replace(/"(.*?)"|'(.*?)'|\/\/(.*?)$|\/\*(.*?)?:(\*\/|$)|\/(.*?)\//g, "");
          addBaseIndentCount  = 0;
      
      // 通常行のインデント数
      Count = baseIndentCount;
      
      // properties検索
      if(checkRow.match(/^properties\b/) !== null){
        propertiesFlg = true;
        propertiesIndentCount = baseIndentCount;
      }
      
      // switch検索
      if(checkRow.match(/^switch\b/) !== null){
          arrSwitchIndentCount.push(baseIndentCount);
          addBaseIndentCount ++;
      }

      // かっこの処理
      // []
      checkRow.replace(/\[/g, 
        function(){
          addBaseIndentCount++;
        });
      checkRow.replace(/\]/g, 
        function(){
          baseIndentCount--;
        });
 
      // {}
      checkRow.replace(/{/g, 
        function(){
          addBaseIndentCount++;
        });
      checkRow.replace(/}/g, 
        function(){
          baseIndentCount--;
          if(arrSwitchIndentCount.length > 0){
            if(baseIndentCount === arrSwitchIndentCount[arrSwitchIndentCount.length - 1] + 1){
              arrSwitchIndentCount.pop();
              baseIndentCount--;
            }
          }
          if(propertiesFlg && baseIndentCount === propertiesIndentCount){
            propertiesFlg = false;
          }
        });

      checkRow.replace(/^\]/g, 
        function(){
          Count = baseIndentCount;
 
        });
      checkRow.replace(/^}/g, 
        function(){
          Count = baseIndentCount;
        });
      
      // case
      if(checkRow.match(/^case\b/) !== null){
        Count --;
      }
      
      // default
      if(checkRow.match(/^default\b/) !== null){
        if(!propertiesFlg){
          Count --;
        }
      }
      
      baseIndentCount += addBaseIndentCount;

      // インデント追加
      rowIndentText = "";
      for(var j = 0; j < Count; j++){
        rowIndentText += indentText;
      }
      row = rowIndentText + row;
    }
      
    // 末行以外に改行コードを追加
    if(i !== rows.length - 1){
      if(tagFlg){
        row += "<br>";
      } else {
        row += "\n";
      }
    }
    
    if(tagFlg){
      //"ダブルコーテーション
      row = row.replace(/"(.*?)"/g, 
                  function() {
                    return '<span class="synConstant">' + arguments[0] + '</span>';
                  });
      //'シングルコーテーション内
      row = row.replace(/'(.*?)'/g, 
                  function() {
                    return '<span class="synConstant">' + arguments[0] + '</span>';
                  });

      // 単行コメント 
      if(row.match(/\/\//) !== null){
        row = row.replace(/\/\//, '<span class="synComment">//') + '</span>';
      }
    }
      
    result += row;
  }

  if(tagFlg){
    // synComment
    // 複数行コメント 開始
    result = result.replace(/\/\*/g, '<span class="synComment">/*');
    // 複数行コメント 終了
    result = result.replace(/\*\//g, '*/</span>');
    // 特殊文字、文字列中
      result = result.replace(/<span class="synConstant">(.+?)<\/span>|<span class="synComment">(.+?)<\/span>/g,
        function() {
          if(arguments[4]){
            return arguments[4];
          } else if(arguments[2] && arguments[1]){
            var special = arguments[0].replace(/\\./g, 
              function(){
                return '<span class="synSpecial">' + arguments[0] + '</span>';
              });
            return '<span class="synConstant">' + special + '</span>';
          }
        });

    // 置換文字列
    var arrReplaceData = [
      ["{", "synIdentifier", "{"],
      ["}", "synIdentifier", "}"],
      ["\\bfunction\\b", "synIdentifier", "function"],
      ["\\bvar\\b", "synIdentifier", "function"],
      ["\\blet\\b", "synIdentifier", "var"],
      ["\\bthis\\b", "synIdentifier", "this"],
      ["\\bif\\b", "synStatement", "if"],
      ["\\belse\\b", "synStatement", "else"],
      ["\\bfor\\b", "synStatement", "for"],
      ["\\bswitch\\b", "synStatement", "switch"],
      ["\\bcase\\b", "synStatement", "case"],
      ["\\bdefault\\b", "synStatement", "default"],
      ["\\bbreak\\b", "synStatement", "break"],
      ["\\bcontinue\\b", "synStatement", "continue"],
      ["\\breturn\\b", "synStatement", "return"],
      ["\\bdo\\b", "synStatement", "do"],
      ["\\bwhile\\b", "synStatement", "while"],
      ["\\bself\\b", "synStatement", "self"],
      ["\\bevent\\b", "synStatement", "event"],
      ["\\barguments\\b", "synStatement", "arguments"],
      ["\\btry\\b", "synStatement", "try"],
      ["\\bcatch\\b", "synStatement", "catch"],
      ["\\bfinally\\b", "synStatement", "finally"],
      ["\\btrue\\b", "synConstant", "true"],
      ["\\bfalse\\b", "synConstant", "false"],
      ["\\bnull\\b", "synConstant", "null"],
      ["\\[", "synIdentifier", "["],
      ["\\]", "synIdentifier", "]"],
      ["\\\\t", "synSpecial", "\\t"],
      ["\\\\", "synSpecial", "\\"]
    ];
    for(var i = 0; i < arrReplaceData.length; i++){
      curReplaceData = arrReplaceData[i];
      result = result.replace(
        new RegExp('(' + curReplaceData[0] + ')|(<span class="synComment">(.+?)<\/span>)|(<span class="synConstant">(.+?)<\/span>)', 'g'),
        function() {
          if (arguments[4]) {
            return arguments[4];
          } else if (arguments[2]) {
            return arguments[2];
          } else if (arguments[1]) {
            return '<span class="' + curReplaceData[1] + '">' + curReplaceData[2] + '</span>';
          }
        });
    }

    // 全体のタグ
    result = '<pre class="code lang-javascript" data-lang="javascript" data-unlink>' + result + '</pre>';
    
    // SEO対策用
    metaText = text.replace(/\n/g, "");
    metaText = metaText.replace(/ {1,}/g, " ");
    metaText = '<meta property="og:description" content="' + metaText.substr(0, 300) + '">';
    
    result = metaText + '\n\n' + result;
  }

  doc.setText(result + '\n\n\n' + text); // 結果を出力する
}

// インデント設定のみ実行
function runTranslateIndent() {
  translate(true, false);
}

// タグ作成のみ実行
function runTranslateTag() {
  translate(false, true);
}

// インデント設定とタグ作成を実行
function runTranslateIndentTag() {
  translate(true, true);
}

// ドキュメントの書式・値を全削除
function clearDoc() {
  DocumentApp.getActiveDocument().clear(); // アクティブドキュメントをクリア
}

// ドキュメントのメニューに追加
function onOpen(){ 
  var ui = DocumentApp.getUi();
  ui.createMenu('コード変換')
      .addItem('インデント設定&タグ作成', 'runTranslateIndentTag')
      .addItem('インデント設定', 'runTranslateIndent')
      .addItem('タグ作成', 'runTranslateTag')
      .addToUi();
  ui.createMenu('文書をクリア')
      .addItem('実行', 'clearDoc')
      .addToUi();
}

5.コードのインデント設定を設定する

 ソースコードの一番上の辺りにある下記の2つの変数をお好みの設定にします。

  var indentText = "    "; // デフォルトのインデントを設定
  var baseIndentCount = 0; // 最小のインデント数を設定
『var indentText = " ";』

 インデント1段あたりの幅です。
 現在は、半角スペース4つにしています。
 『var indentText = "\t";』とするとタブが設定できます。
 逆スラッシュはキーボードの『option + ¥』(Windowsは『alt + ¥』)です。

『var baseIndentCount = 0;』

 インデント1段を1として、最低いくつにするかを設定します。

6.コードを保存

  1. 『保存』ボタンをクリック
    f:id:mmorley:20160514223810p:plain
  2. プロジェクト名を入力して『OK』をクリック
    名前は何でも構いません。
    f:id:mmorley:20160514224012p:plain:w400

7.ドキュメントシートにメニューを追加

 『コード変換』メニューを追加します。

  1. 『実行』-『onOpen』をクリック
    f:id:mmorley:20160514224416p:plain:w400
  2. 『許可を確認』をクリック
    f:id:mmorley:20160514224547p:plain:w400
  3. 『許可』をクリック
    f:id:mmorley:20160514225015p:plain:w450

 ドキュメントに戻ると、メニューに『コード変換』と『文書をクリア』が追加されています。
f:id:mmorley:20160514225955p:plain
 
 設定は以上です。

使い方

 googleドキュメントにJavaScriptソースコードを貼り付けます。

  • メニューの『コード変換』-『インデント設定』をクリックするとインデントが設定し直されます。
  • メニューの『コード変換』-『タグ作成』をクリックするとインデントはそのままではてなブログ用のタグが作成されます。
  • メニューの『コード変換』-『インデント設定&タグ作成』をクリックするとインデントを設定しなおしてから、はてなブログ用のタグが作成されます。

 
 作成されるタグは、装飾用のタグで内容(ソースコード)とぎれとぎれになるため、に最初から300文字分が収められています。これは記事内には表示されません。
 
 変換されたソースコードは、元のコードの前に表示されます。
f:id:mmorley:20160514232004p:plain:w500

あとがき

 以前にこちらの記事で、googleスプレッドシートスクリプトで操作しました。
mmorley.hatenablog.com
 
 興味がわいたので、今度はgoogleドキュメントを操作してみました。
 だいぶ使う人が限られたものを作ってしまった感はありますが、ドキュメントの操作等の勉強になりました。
 
 ソースコードは、はてな記法で簡単な書き方がありますが、リストの連番が途切れるのでHTMLタグしたいと思ったので作ってみました。
 前回のテーブルタグと同じ動機です。
 
 スクリプトを書いていて、ちょっと謎仕様があったのですが、

  • スプレッドシートで使えた『Browser.msgBox("メッセージ"); 』のメッセージボックスが、ドキュメントだと使えない。
  • 『DocumentApp.getUi().alert("メッセージ"); 』のメッセージボックスは、インデントが勝手に削除される。

 等がありました。