最近では多くの人はWebブラウザに向かって仕事をしています。そうであれば、ちょっとした作業もブラウザ上でできると便利です。今回、JavaScriptでプログラムを作って簡単なデータの文字列整形をする方法を紹介します。

  • 今回作成する文字列整形プログラム

    今回作成する文字列整形プログラム

テレワークが加速するとブラウザ作業が増える?!

テレワークが推奨される昨今その流れは加速しています。なぜなら、機器を問わず、WindowsでもmacOSでもiPadでもAndroidタブレットでも、好きな機材を利用して資料の確認や作成ができるからです。

今回、テレワークのために多くの人が機材を購入しましたが、全ての職場で良い機材を支給できたわけではありません。既に手元にある機器で作業をしてもらえるなら理想的です。スマートフォン、タブレット、PC、いずれの機器にもブラウザは搭載されています。Webアプリを利用する流れが一層加速していくことでしょう。

編集部の仕事をJSで自動化しよう

さて、今回作る文字列整形のプログラムですが、編集部で行われている作業を自動化したいという相談から始まっています。編集部では定期的にメールマガジンを発行していますが、これはニュースサイトに日々アップされる記事の要約をメールでお知らせするというものです。

しかし、サイト上の記事をメールマガジンの書式に落とし込むのは、それなりに労力が必要です。サイト上の記事の一覧がWebシステムから取得できるようになっていますが、それを綺麗に番号付けし、また、タイトルをタグ付けして、読者に読みやすく整形した上で提供するのです。

実際、こうした簡単な整形処理というのは、あちらこちらで定期的に行われています。手作業でパパッとやることが多いのですが、定期的に行われる作業はプログラミングで自動化すると便利です。もちろん、こうした作業には全く汎用性がないのですが、JavaScriptを使った文字列整形作業をどのように自動化するのかの参考になります。また、お題として面白いので取り組んでみましょう。それでは、お題から確認してみましょう。

【お題】

Webシステムから記事タイトルとURLの一覧が出力されます。記事のそれぞれに対して、連番をつけてください。

入力データである記事タイトルとURLの一覧は以下のようなものです。よくよく見ると分かりますが、記事タイトル、URL、記事タイトル、URL ... と交互に配置されています。

オンライン結婚式場見学を開始したノバレーゼの成約に向けた取組
https://news.mynavi.jp/article/20200619-1056453/
Windows 10にUbuntu 20.04 LTSをインストールする
https://news.mynavi.jp/article/liunx_win-51/
ノートPCと周辺機器の連係が一気に楽になる「ドッキングステーション」
https://news.mynavi.jp/kikaku/beginner_pc-3/

これを以下のように出力します。

[ 1] オンライン結婚式場見学を開始したノバレーゼの成約に向けた取組
     https://news.mynavi.jp/article/20200619-1056453/
[ 2] Windows 10にUbuntu 20.04 LTSをインストールする
     https://news.mynavi.jp/article/liunx_win-51/
[ 3] ノートPCと周辺機器の連係が一気に楽になる「ドッキングステーション」
     https://news.mynavi.jp/kikaku/beginner_pc-3/

基本的な画面を作ろう

まず、こうしたツールを作るときに気をつけたいのが、できるだけ手軽に整形を行いたいという点です。自分が使うだけであれば、プログラムをさっと書いて終わりでも良いのですが、もし誰かに使ってもらおうと思っている場合は、実行手順を簡単にすることが大切です。

ちょっとテキストを整形するだけなのに、データをファイルに保存して、コマンドラインを起動してコマンドを打ち込んでもらってプログラムを実行して・・・というプログラマー以外の人に馴染みのない作業を強要することはできません。この点、Webブラウザで動くアプリなら、HTMLファイルをブックマークしてもらって、ブラウザでそのHTMLファイルを開くだけで動かすことができます。

それで、画面に入力と出力の二つのテキストボックスを配置し、入力用のテキストボックスに入力データをコピー&ペーストで貼り付けると、整形後のテキストを出力用のテキストボックスに出力するという仕組みで作ってみましょう。

  • UIだけを作ってみたところ

    UIだけを作ってみたところ

HTMLは次のようなものになるでしょう。

<!DOCTYPE html><html><meta charset="utf-8"><body>
<h3>入力 - 以下にタイトルとURLの一覧を貼り付け</h3>
<textarea id="in_ta" rows="8" cols="80"></textarea>
<h3>出力</h3>
<textarea id="out_ta" rows="8" cols="80"></textarea>
<script>
  // ここで整形プログラム
</script>
</body></html>

変換プログラムを作ろう

さて、このようにデータ整形のプログラムを作る時の戦略として、まずは入力データをJavaScriptで扱いやすい形で取得しておいて、その後で好きな形で出力するという手法が使えます。今回のような簡単な整形であれば、入力データを読みながらデータを整形して出力という手法もできるのですが、プログラムはできるだけ単純にしておくと、改良が容易になります。

最初に、HTMLのテキストボックス(textarea)からテキストを取り出し、データが入力された段階でデータを出力するようにしてみます。

// 入力と出力のテキストボックスのDOMを取得 --- (*1)
const in_ta = document.querySelector("#in_ta")
const out_ta = document.querySelector("#out_ta")
in_ta.onkeydown = convertTextFromTA // イベント設定

// 整形処理を実行
function convertTextFromTA() {
  // 入力を得る --- (*2)
  const lines = getInputArray(in_ta.value)
  // 出力を生成 --- (*3)
  out_ta.value = convertText(lines)
}

プログラムの(*1)の部分では、JavaScriptでテキストボックスを操作できるように、DOMオブジェクトを取得します。そして、onkeydownのイベントを設定することで、テキストボックス内で何かキーを押した時に、convertTextFromTA関数が実行されるようにします。

(*2)の部分では、入力テキストボックス(in_ta)の値を取得し、それをJavaScriptで扱いやすい配列(Array)形式 で取得します。(*3)の部分では、整形済みのテキストを出力テキストボックス(out_ta)に設定します。なお、getInputArray関数とconvertText関数はこの後で作成します。

入力テキストを配列形式で取得しよう

それでは、入力テキストを配列形式で取得するプログラム、getInputArray関数を作ってみましょう。入力テキストを改行で区切って各行を調べます。その際、タイトル、URL、タイトル、URLと交互にデータが並んでいることを利用して、2行一組でデータを取得することです。以下がプログラムです。

// 入力データを配列形式で得る
function getInputArray(textData) {
  // 前後の空白をトリム --- (*1)
  const data = textData.replace(/^\s+/, '').replace(/\s+$/, '')
  // 改行コードを揃えて一行ずつに分解 --- (*2)
  const lines = data.replace(/\r\n/g, "\n").split("\n")
  // タイトルとURLの組に分ける --- (*3)
  const result = []
  let title = "", url = ""
  for (let i in lines) { // 各行を調べる
    let line = lines[i]
    if (i % 2 == 0) { // 2行ごと交互にデータを得る
      title = line
      continue
    }
    url = line
    result.push([title, url])
  }
  return result
}

2行ごとにデータを配列に追加するだけですが、入念な前置処理が必要です。まず、(*1)の部分では、テキストボックスの前後にある空白を削除します。replaceメソッドで、正規表現を利用して空白を削除します。

(*2)の部分では改行コードを揃えつつ、一行ずつに分割します。OSごとにテキストの改行コードが異なります。WindowsではCRLF(\r\n)、Linux/macOSではLF(\n)の改行が使われます。そこで、最初にCRLF(\r\n)をLF(\n)に統一します。そして、splitメソッドでLF(\n)で行を分割します。

そして、(*3)の部分でfor構文を利用して一行毎にデータを調べます。その際、タイトルとURLが繰り返されるため、行番号を2で割った余りが0の時にタイトルを覚えておいて、1の時にタイトルとURLをまとめて結果配列(result)に追加するようにします。

出力テキストを作成しよう

続いて、配列形式のデータからテキストを出力するプログラムを作っていきましょう。入力データは、以下のような配列データとなっています。

[[タイトル,URL], [タイトル,URL], ... ]

このようなを受け取って番号をつけてデータを出力します。その際、数値はスペースを入れて右寄せします。

// テキストに変換
function convertText(input) {
  const result = []
  // 入力を繰り返し出力 --- (*1)
  for (let i in input) {
    const line = input[i]
    const title = line[0] // タイトル
    const url = "     " + line[1] // URL
    const no = pad2(parseInt(i) + 1)
    result.push(`[${no}] ${title}\n${url}`)
  }
  return result.join("\n")
}

// スペースを入れて二桁右寄せで揃える --- (*2)
function pad2(s) {
  const n = "  " + s
  return n.substr(n.length - 2, 2)
}

(*1)の部分でfor構文を利用して繰り返しデータを処理します。(*2)の部分では、数字の前にスペースを入れて二桁右寄せに揃えるpad2関数を定義しています。

実行してみよう

なお、ここまでの完全なプログラムをこちらにアップしました。ソースコードの部分を「convert-text.html」という名前で保存し、Webブラウザにドラッグ&ドロップして実行してみてください。

  • 実行したところ

    実行したところ

形成プログラムのまとめ

今回作ったのは、入力データに番号をつけて出力するだけと簡単なものでした。実は、もう少し複雑な処理が必要になります。次回は今回のプログラムをベースに改造していきます。お楽しみに。

自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。