@wikiに貼れる、CSVをWikiの表組み書式に変換するJavaScript
10/07/25更新
連続するダブルクオーテーションがダブルクオーテーションを表すのはエスケープされているときのみにした
今取り掛かってるWikiが大きな表をバンバン作るものなんですが、いちいち手動で打ち込むのは大変なので、表計算ソフトとかで作った表を変換できればいいなと考えてCSVから表組み書式に変換するJavaScriptを作ろうと思いました。*1
で、都合よく、借りてる@wikiではJavaScriptが使えたので、Wikiに埋め込めるようなスクリプトを作りました。
使用例http://www23.atwiki.jp/freegamemusic/pages/27.html
JavaScriptは初心者同然なので、非効率な書き方やバグなどあると思いますが、もし何か気になるところがありましたら指摘してくださるとありがたいです。
仕様
補足
- 比較演算子を使ってないのは、@wikiに上げたときに実体参照に変換されてしまうからです
- returnでの戻り値にカッコをしてスペースを入れないようにしているのは、@wikiに上げたとき、returnと戻り値の間に改行が挟まれて意味が変わらないようにするためです
- 特に意識してませんが、同様の理由で文字列リテラルには半角スペースを入れるべきではないでしょう
- 匿名関数の終わりに';'を付けているのは、逆に改行が取り除かれてしまうため
- 長いswitch文はあまりよくないですね
var thisScript = (function (e) { if(e.nodeName.toLowerCase() == 'script') return e; return(arguments.callee(e.lastChild)) })(document); var thisScriptParent = thisScript.parentNode; function createButton(id,value) { var button = document.createElement('input'); button.id = id; button.type = 'button'; button.value = value; thisScriptParent.appendChild(button); return(button); } function createTextArea(id) { var textarea = document.createElement('textarea'); textarea.id = id; textarea.cols = 10; textarea.rows = 10; textarea.style.width = '100%'; thisScriptParent.appendChild(textarea); return(textarea); } function resizeTextArea(textarea) { var limit = 10;/* これ以上は小さくならないようにする */ var lines = textarea.value.split('\n').length; var tmp = lines; for (;;) { if (tmp == limit) { tmp = lines; break; } else if (tmp == 0) { tmp = limit; break; } tmp--; } textarea.rows = tmp; } function csv2table(text) { var escape = false;/* エスケープフラグ */ var bol = true;/* 行頭フラグ */ var i = 0; var textArray = text.split(''); textArray.push(null);/* 番兵 */ for (;;) { if (bol) { textArray.splice(i,0,'|'); i++; } var c = textArray[i]; if (c == null) {/* 番兵が見つかったので終了 */ textArray.pop(); break; } switch (c) { case ',': if (escape == false) { textArray[i] = '|'; } i++;/* gotoでdefaultに飛びたい… */ bol = false; break; case '\"': textArray.splice(i,1); if (escape) { if (textArray[i] == '\"') {/* エスケープされたダブルクオート */ i++; } else { escape = false; } } else { escape = true; } bol = false; break; case '\r\n': case '\r': case '\n': if (escape) {/* セル内改行 */ textArray[i] = '&br()'; i++; } else { if (bol) { textArray.splice(i-1,2); i--; } else { textArray.splice(i,0,'|'); i += 2; } bol = true;/* エスケープしてないときにのみ行頭フラグオン */ } break; case '|': textArray[i] = '|'; default:/* 置換する以外はその他の文字と一緒 */ i++; bol = false; break; } } if (bol) { textArray.pop(); } else { textArray.push('|'); } return(textArray.join('')); } new function () { var idTextArea = 'my_textarea'; var idConvert = 'my_buttonconvert'; var idUndo = 'my_buttonundo'; var prevText = ""; var isConverted = false; var buttonConvert = createButton(idConvert,'変換'); var buttonUndo = createButton(idUndo,'元に戻す'); var textArea = createTextArea(idTextArea); textArea.onkeyup = function () { resizeTextArea(textArea); }; buttonConvert.onclick = function () { prevText = textArea.value; textArea.value = csv2table(prevText); isConverted = true; resizeTextArea(textArea); }; buttonUndo.onclick = function () { if (isConverted) { textArea.value = prevText; resizeTextArea(textArea); } }; };
参考にさせていただいたサイト
*1:何でJavaScriptでやろうとしたかというと、ブラウザの別のタブで開いておけば編集時に便利だと思ったから