正規表現がんばって、規約をマークアップするアプリつくってみた

こんにちは、榊原です。
 
最近、アプリリリースにしたがって、アプリの規約のマークアップをすることがちょいちょいあります。そりゃ、規約ですので、dl,dt,ddでマークアップするのですが、まぁ、これが単純作業。
1つだけでしたら「仕方ないか」と単純作業に従事するのですが、それが2つ3つになってきて規約のバージョンアップも見据える必要がでてきたので、自動的にマークアップするアプリを作ってみました。
 
規約マークアップ
 
ちなみに自分の業務効率化目的で作ったので、あまり汎用性はないです。法律とかコピペしても全然マークアップされないので、利用の際はご了承下さい。

 

正規表現がんばってみた

さて、規約マークアップは、正規表現を使って実装しています。「正規表現はサンプルをコピペするもの」と数年逃げてたのですが、いい加減に向かいあわないといけない気がしてがんばってみました。まだまだひよっこですが、使ってみると存外便利で、これからも活用できそうな感じです。

ここでは、どうやって正規表現で実現したかを軽く説明します。正規表現の書き方、ってより概念中心ですー。

1. 各条毎に区切る

    let terms = '\n' + this.termsInput;
    let splitArray = terms.split(/[\n|\r|\n\r](第(\d{1,2}|[0-9]{1,2})条.*)(\n|\r|\n\r)/g);

最初は「どのように一発の正規表現でマークアップできるか」を考えたのですが、正規表現といえど万能ではないです。具体的には、「ここだけに適応したい」と思ってるのに、予定していないところにも適応したりします。まぁ、当たり前といえば当たり前。
そこで、正規表現適応の範囲を把握するために、条文毎に区切って連想配列に格納しました。

2. 条文毎に連想配列に格納する

    let skipArray = [];
    let tmpArticle;
    splitArray.forEach(function(txt:string)
    {
      if(txt.length > 3){
        if(i%2 == 0){
          tmpArticle = txt;
        }else{
          skipArray = skipArray.concat({article:tmpArticle,provision:txt});
        }
        i++;
      }
    });

とはいえ、きれいに条文だけで切れるわけではないので、「(改行)第◯条(改行)」を区切り文字にしました。すると、空白だけとか改行だけとかいうのも込みの連想配列(splitArray)ができあがりますので、それを展開して3文字以上の配列を使ってskipArrayを再構築しています。奇数は条文、偶数は本文という取り回しをしています。
 
なので、このアプリだと、前文があると、奇数偶数が狂うとか、必ず条文と本文は対になるように書いてくれみたいな縛りができてしまいました(ま、業務上はいっかと)
 

3. 本文内の条項の取り回し

で、規約の本文というのは面倒なもので、本文の中に条項とかリストが入ってきます。これは、ol,liでくくりたいし、しかもこいつが入れ子構造になってやがる!
ということで、本文の中で、「第(半角|全角数字)条」もしくは「(半角|全角数字).」と表記したものを条項として取り扱います。まずは、条項があるかないかを確認。
 

if(val.match(/(\n|\r|\n\r)(第(\d{1,2}|[0-9]{1,2})項|(\d{1,2}|[0-9]{1,2})(\.|.))/g))

 
あった場合は、先ほどと同じように区切って連想配列に放り込みます。こちらは前文がある場合は[0]に格納されますので、[0]の文字数が1文字以上あった場合は前文として取り扱います。
 

  private _makeList(val:string)
  {
    let expression = /(\n|\r|\n\r)(第(\d{1,2}|[0-9]{1,2})項|(\d{1,2}|[0-9]{1,2})(\.|.))/g;
    if(val.match(expression)){
      let spliteArray = val.split(expression);

      // 前文取得
      let preface = "";
      if(spliteArray[0].length > 1){
        preface = spliteArray[0] + '\n';
        delete spliteArray[0];
      }

      let that = this;
      let list = "  <ol>\n";
      spliteArray.forEach(function(txt:string)
      {
        if(txt && txt.length > 3){
          txt = that._makeDetailList(txt,/([Ⅰ-Ⅹ]{1,2}|[ⅰ-ⅹ]{1,2}|(\d{1,2}|[0-9]{1,2})号)/g);
          list += '    <li>\n      ' + txt + '    </li>\n';
        }
      });
      list += '  </ol>\n';

      return preface + list;
    }else{
      return val;
    }
  }

 

まとめ

取り留めのないコードを書いた記事になってしまいましたが、正規表現便利!ということで。
「正規表現入門」みたいなもので1から覚えていくのもひとつではありますが、それではなかなかはじめられないって方は、ひとつテーマをつくって小さなアプリをつくってみるといい勉強になりおすすめです。
 
それでは、また。

お問い合わせ