0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

メモ:dokuwiki の表を markdown に変換する

Posted at

個人的なメモです。

要件の検討

  • dokuwiki ではセルは結合できるけれど、それは変換できなくても仕方がないものとする
  • dokuwikiでは行毎にセルの左右寄せを変えることができるけれど、markdownでは列単位でしかできないので、2行目の中寄せ・右寄せが後続の行でも使われるものとする

入出力の形式

入力

  • 見出し行は /^(\^[^^]*)+\^$/
  • 後続行は /^(\|[^\|]*)+\|$/
    • 繰り返しの回数は見出し行と同じでなければならない(はずなのだが簡単のためテストはしない)
  • 最初の後続行(表の第2行)について各セル(|で分割した各要素)が:
    • /^␣␣.*␣␣$/ ならば当該列は中寄せに
    • そうではなく、/^␣␣/ ならば当該列は右寄せに
    • そうではなければ当該列は左寄せに

(ここでスペースはわかりにくいので ␣ ␣ で代えました)

出力

  • 見出し行は |\| に置換してから ^| に置換して出力(以下、見出し変換と呼ぶ)
  • 後続行はそのまま出力
    • ただし、最初の後続行を出力する前に、左右中寄せ指定を出力

分析

状態遷移図

種類の違う行を受け取ったときにプログラムの挙動が違うので、抜けがないように考えてみます。

こういうのを有限状態オートマトンといいます。

状態遷移表

慣れれば状態遷移図を見ながらコーディングできますが、ねんのため状態×入力の表にしてみましょう。

見出し行 後続行 その他の行
初期状態 見出し変換出力; 見出し認識状態へ そのまま出力 そのまま出力
見出し認識状態 そのまま出力; 初期状態へ 左右中寄せ指定出力; そのまま出力; 後続行認識状態へ そのまま出力; 初期状態へ
後続行認識状態 そのまま出力; 初期状態へ そのまま出力 そのまま出力; 初期状態へ

あとはガリガリコーディング

たとえば JavaScript ならなんかこんな感じで動く。

 function convert(){
 let val = document.getElementById("text-area").value;
 let lines = val.split(/\r\n|\n/);
 let text = [];
 let state = 0;
 for (var line of lines) {
  if (state === 0) {
    if (/^(\^[^^]*)+\^$/.test(line)) {
      line = line.replace(/\|/g, "\\|");
      line = line.replace(/\^/g, "|");
      state = 1;
    }
  } else if (state === 1) {
    if (/^(\|[^\|]*)+\|$/.test(line)) {
      let cols = line.split(/\|/);
      cols.shift();
      cols.pop();
      let colspec = cols.map(function (col){
        if (/^  \.*  $/.test(col)) {
          return ':---:';
        } else if (/^  /.test(col)) {
          return '---:';
        } else {
          return ':---';
        }
      });
      colspec.unshift('');
      colspec.push('');
      text.push(colspec.join('|'));
      state = 1;
    } else {
      state = 0;
    }
  } else if (state === 2) {
    if (!(/^(\|[^\|]*)+\|$/.test(line))) {
      state = 0;
    }
  }
  line = line.replace(/^======\s*(.*)\s*======$/, "# $1");
  line = line.replace(/^=====\s*(.*)\s*=====$/, "## $1");
  line = line.replace(/^====\s*(.*)\s*====$/, "### $1");
  line = line.replace(/^===\s*(.*)\s*===$/, "#### $1");
  line = line.replace(/^==\s*(.*)\s*==$/, "##### $1");
  // 一行に複数リンクがあるときのバグは直したよ
  line = line.replace(/\[\[([^[\|]*)\|([^[]*)\]\]/g, "[$2]($1)");
  text.push(line);
 }
 let txt = document.getElementById("output");
 txt.innerHTML = text.join("\r\n");
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?