kramdown を使って Markdown をパースしてあれこれる


一般人にMarkdownを書いてもらって、それをうまいことなんらかに使いたいなぁーと。

そもそも、HTMLに一発で変換してくれるステキなライブラリはあるけれど、パースした結果が欲しいってのはあるのかないのかピンとこなかったので、[kramdown](http://kramdown.gettalong.org/rdoc/index.html)を調べてみた。

# 導入

``` shell-session
gem install kramdown
```

# コード

## 抜粋

``` main.rb

def own_inspect(node, deep)
  deep_puts(
    "TYPE:#{node.type} => VALUE:'#{node.value}' / ATTR:'#{node.attr}'",
    deep
  )
  node.children.each do |child|
    own_inspect(child, deep + 1)
  end
end

doc =  Kramdown::Document.new(text)
deep = 0
own_inspect(doc.root, deep)
```

textを読み込ませてパース。結果は、doc.rootを手繰っていけばよい。runできるコードは最下段参照。



# まとめ

何にパースされたのか？は `.type` を見ればOKで、中身は `.value` で取ればOK。

子要素はchildrenで取れる。

リンクなどなどは、 `.attr[]` にある。基本 `.type` で分岐すればあれこれできるようだ。

しかし、がんばるより、htmlに置き換えたものをhtmlパーサに食わせて操作したり、置換したりしたほうが早い気がするね・・・。


# 動くものと動作ログ

``` main.rb
require 'kramdown'

def deep_puts(v, deep)
  deep.times { print '  ' }
  puts v
end

def own_inspect(node, deep)
  deep_puts(
    "TYPE:#{node.type} => VALUE:'#{node.value}' / ATTR:'#{node.attr}'",
    deep
  )
  node.children.each do |child|
    own_inspect(child, deep + 1)
  end
end


text = <<EOS
#aaa
e

#ccc

- h
- i
  - ii
  - iii

#inline
abc **def** ghi

# Image
![Qiita](http://qiita.com/icons/favicons/public/apple-touch-icon.png "Qiita")

# Link
[blog]('http://blog.phalanxware.com')

EOS

doc =  Kramdown::Document.new(text)
puts doc.to_html

deep = 0

own_inspect(doc.root, deep)
```

実行結果

``` shell-session
$ ruby main.rb
<h1 id="aaa">aaa</h1>
<p>e</p>

<h1 id="ccc">ccc</h1>

<ul>
  <li>h</li>
  <li>i
    <ul>
      <li>ii</li>
      <li>iii</li>
    </ul>
  </li>
</ul>

<h1 id="inline">inline</h1>
<p>abc <strong>def</strong> ghi</p>

<h1 id="image">Image</h1>
<p><img src="http://qiita.com/icons/favicons/public/apple-touch-icon.png" alt="Qiita" title="Qiita" /></p>

<h1 id="link">Link</h1>
<p><a href="'http://blog.phalanxware.com'">blog</a></p>

TYPE:root => VALUE:'' / ATTR:'{}'
  TYPE:header => VALUE:'' / ATTR:'{}'
    TYPE:text => VALUE:'aaa' / ATTR:'{}'
  TYPE:p => VALUE:'' / ATTR:'{}'
    TYPE:text => VALUE:'e' / ATTR:'{}'
  TYPE:blank => VALUE:'
' / ATTR:'{}'
  TYPE:header => VALUE:'' / ATTR:'{}'
    TYPE:text => VALUE:'ccc' / ATTR:'{}'
  TYPE:blank => VALUE:'
' / ATTR:'{}'
  TYPE:ul => VALUE:'' / ATTR:'{}'
    TYPE:li => VALUE:'' / ATTR:'{}'
      TYPE:p => VALUE:'' / ATTR:'{}'
        TYPE:text => VALUE:'h' / ATTR:'{}'
    TYPE:li => VALUE:'' / ATTR:'{}'
      TYPE:p => VALUE:'' / ATTR:'{}'
        TYPE:text => VALUE:'i
' / ATTR:'{}'
      TYPE:ul => VALUE:'' / ATTR:'{}'
        TYPE:li => VALUE:'' / ATTR:'{}'
          TYPE:p => VALUE:'' / ATTR:'{}'
            TYPE:text => VALUE:'ii' / ATTR:'{}'
        TYPE:li => VALUE:'' / ATTR:'{}'
          TYPE:p => VALUE:'' / ATTR:'{}'
            TYPE:text => VALUE:'iii' / ATTR:'{}'
  TYPE:blank => VALUE:'
' / ATTR:'{}'
  TYPE:header => VALUE:'' / ATTR:'{}'
    TYPE:text => VALUE:'inline' / ATTR:'{}'
  TYPE:p => VALUE:'' / ATTR:'{}'
    TYPE:text => VALUE:'abc ' / ATTR:'{}'
    TYPE:strong => VALUE:'' / ATTR:'{}'
      TYPE:text => VALUE:'def' / ATTR:'{}'
    TYPE:text => VALUE:' ghi' / ATTR:'{}'
  TYPE:blank => VALUE:'
' / ATTR:'{}'
  TYPE:header => VALUE:'' / ATTR:'{}'
    TYPE:text => VALUE:'Image' / ATTR:'{}'
  TYPE:p => VALUE:'' / ATTR:'{}'
    TYPE:img => VALUE:'' / ATTR:'{"src"=>"http://qiita.com/icons/favicons/public/apple-touch-icon.png", "alt"=>"Qiita", "title"=>"Qiita"}'
  TYPE:blank => VALUE:'
' / ATTR:'{}'
  TYPE:header => VALUE:'' / ATTR:'{}'
    TYPE:text => VALUE:'Link' / ATTR:'{}'
  TYPE:p => VALUE:'' / ATTR:'{}'
    TYPE:a => VALUE:'' / ATTR:'{"href"=>"'http://blog.phalanxware.com'"}'
      TYPE:text => VALUE:'blog' / ATTR:'{}'
  TYPE:blank => VALUE:'
' / ATTR:'{}'
```