hatenablog gemでタグ付きの文章が出力できない問題を解決した

色々とコード書き換えながら試したいのでローカルにbundle installする。

$ bundle install --path vendor/bundle

これでvendor/bundle以下にあるgemファイルを書き換えることでライブラリの挙動を変えたりpしながら調べることができる。

コードを読んでいくとxmlにエスケープが入っていないことが分かった。rubyでシンプルなXML escape。なので以下のようにエンコード関数を渡すことで動くようになった。

def entry_xml(title = '', content = '', categories = [], draft = 'no', updated = '', author_name = @user_id)
  .
  .
  xml % [e(title), author_name, e(content), updated, categories_tag, draft]
end

足したe()関数はこんな感じ。

def e(str)
  str.encode(xml: :text)
end

うまく行ったぜー、とプルリクエスト送ろうと思ったらkymmt90/hatenablogにあるコードと中身が違う、あれ?よくみるとbundle installで入っているのはhatenablog-0.2.1だけど最新はhatenablog-0.2.2であることに気がついた。これはもしかして・・・結局マージリクエストは以下のようになった。

Update hatenablog to 0.2.2 by ongaeshi · Pull Request #2 · kymmt90/hatenablog-writer

これで以下のようなタグ付きのテキストも問題なく投稿できるようになった。

<html>
</html>

hatenablog gemでタグ付きの文章が出力できない問題を解決した

色々とコード書き換えながら試したいのでローカルにbundle installする。

$ bundle install --path vendor/bundle

これでvendor/bundle以下にあるgemファイルを書き換えることでライブラリの挙動を変えたりpしながら調べることができる。

コードを読んでいくとxmlにエスケープが入っていないことが分かった。rubyでシンプルなXML escape。なので以下のようにエンコード関数を渡すことで動くようになった。

    def entry_xml(title = '', content = '', categories = [], draft = 'no', updated = '', author_name = @user_id)
      .
      .
      xml % [e(title), author_name, e(content), updated, categories_tag, draft]
    end

足したe()関数はこんな感じ。

    def e(str)
      str.encode(xml: :text)
    end

うまく行ったぜー、とプルリクエスト送ろうと思ったらkymmt90/hatenablogにあるコードと中身が違う、あれ?よくみるとbundle installで入っているのはhatenablog-0.2.1だけど最新はhatenablog-0.2.2であることに気がついた。これはもしかして・・・結局マージリクエストは以下のようになった。

Update hatenablog to 0.2.2 by ongaeshi · Pull Request #2 · kymmt90/hatenablog-writer

これで以下のようにタグ付きの文章でも問題なく投稿できるようになった。 :smile:

<html>
</html>

はてなブログをコマンドラインから投稿できるようにした

この記事がすでにコマンドラインで投稿している。 hateblog-writeというのをインストールしてみた。

インストール

はてなブログ API 用の gem を書いた - blog.kymmt.comに沿ってコンシューマキー、アクセストークンの順に取得、config.ymlを生成すればよい。

落とし穴1 権限

read_private, write_private はデフォルトOFFなので注意。全ての権限を有効にしておくこと。

$ get_access_token CONSUMER_KEY CONSUMER_SECRET
/opt/local/lib/ruby2.3/gems/2.3.0/gems/oauth-0.4.7/lib/oauth/consumer.rb:178:in `request': parameter_rejected (OAuth::Problem)
    from /opt/local/lib/ruby2.3/gems/2.3.0/gems/oauth-0.4.7/lib/oauth/consumer.rb:194:in `token_request'
    from /opt/local/lib/ruby2.3/gems/2.3.0/gems/oauth-0.4.7/lib/oauth/consumer.rb:136:in `get_request_token'
    from /opt/local/lib/ruby2.3/gems/2.3.0/gems/hatenablog-0.2.2/exe/get_access_token:26:in `get_request_token'
    from /opt/local/lib/ruby2.3/gems/2.3.0/gems/hatenablog-0.2.2/exe/get_access_token:50:in `get_access_token'
    from /opt/local/lib/ruby2.3/gems/2.3.0/gems/hatenablog-0.2.2/exe/get_access_token:60:in `<top (required)>'
    from /opt/local/bin/get_access_token:23:in `load'
    from /opt/local/bin/get_access_token:23:in `<main>'

落とし穴2 config.yml

うまくいかないときは大抵の場合config.ymlの設定をミスっている。はてなブログIDはドメインを指定する。私だったらongaeshi.hatenablog.comとか。

consumer_key: <コンシューマキー>
consumer_secret: <コンシューマシークレット>
access_token: <アクセストークン>
access_token_secret: <アクセストークンシークレット>
user_id: <ユーザ ID>
blog_id: <はてなブログ ID>
.
.
.
blog_id: ongaeshi.hatenablog.com

落とし穴3 ロケール

ロケールを設定しておかないと日本語を含むマークダウンを投稿できないので注意。以下を~/.profile~/.bashrcに設定。

export LC_ALL=ja_JP.UTF-8
export LANG=ja_JP.UTF-8

使い方

$ cd ~/Documents/hatenablog-writer
$ cat blog/001/md
Test

This is test

投稿

$ bundle exec hw -c diary blog/001.md

更新

$ bundle exec hw -u blog/001.md

改造

hatenablog-writer/hw に以下のコードを足すと更新後に記事のURLを出力してくれて幸せになれます。

HBWriter.new do |hb_writer|
  ARGV.each do |file_name|
    entry_text = ''
    open(file_name, 'r') do |f|
      if OPTS[:d]
        entry_text = hb_writer.delete_entry(f.read)
      elsif OPTS[:u]
-        hb_writer.update_entry(f.read, CATEGORIES)
+        e = hb_writer.update_entry(f.read, CATEGORIES)
+        puts e.uri
      elsif OPTS[:m]
        hb_writer.minor_update_entry(f.read, CATEGORIES)
      else
        entry_text = hb_writer.post_entry(f.read, CATEGORIES)
      end
    end
$ bundle exec hw -u blog/001.md
http://ongaeshi.hatenablog.com/entry/hatenablog-writer

バグ報告

動かないパターンを見つけたのでIssueに登録した。

contentに'<'が含まれるとエラー · Issue #1 · kymmt90/hatenablog-writer

RubyPico開発日記2 - SimpleHttpServerを2回起動するとserver.rb:50 bind (RuntimeError)

こんな感じ。

f:id:tuto0621:20160731154021p:plain

おそらく一度ソケットで確保したアドレスがプログラム終了後にcloseされずに確保しっぱなしになっているようだ。RubyPico自体を終了させると解放される。

CRubyはプロセスとして起動する場合が多いのでWebサーバーを止めたいときはそのプロセスを停止してしまえばよい、OSが安全に後始末してくれる。ところがiOSのアプリは子プロセスが作れない(forkできない)ので、RubyPicoは別スレッドでmrubyを動かしているのでプログラム終了時にこちらでなんとかしないといけない。プログラム終了後にはmrb_close()が呼ばれるのでそのタイミングで未解放のソケットがあればcloseする、例えばGC時に後始末関数を呼ぶような仕組みがいいのだろうか。

RubyにはFinalizerがあったがgrepした感じmrubyにはない。なのでRubyPicoのImageクラスのようにcloseされていなかったら解放時にcloseを呼ぶようなライブラリを用意するのがいいのかしら?

もしくはiOS用に用意されたCocoaHTTPServerというのがあるのでこいつをRubyPico用にバインドするのもいいかもしれない。でも、低レイヤのソケットライブラリが用意されているとどうやってHTTPが動いているのかを勉強するのにいいんだよなぁ、実際mruby-simplehttpserverはたった180行のRubyスクリプト書かれていて、私自身Webサーバがどうやって動いているのか理解するのにとても役立った。runとか関数の内容をRubyPico上でオーバーライドすれば簡単に挙動を変えて確かめられるしね。(ここがRubyのすごいところだと思う)

RubyPico開発日記1 - iOSからWebサーバーを起動する

RubyPicoが内部で使っているmrubyを1.2に上げたのでmatsumoto-r/mruby-simplehttpserverコンパイルできるようになった。以下のようなプログラムを書くとイントラネット内でwebサーバーを起動できるようになる。

# 
# Server Configration
# 

server = SimpleHttpServer.new({

  :server_ip => "0.0.0.0",
  :port  =>  8000,
  :document_root => "./",
})


#
# HTTP Initialize Configuration Per Request
#

# You can use request parameters at http or location configration
#   r.method
#   r.schema
#   r.host
#   r.port
#   r.path
#   r.query
#   r.headers
#   r.body

server.http do |r|
  server.set_response_headers({
    "Server" => "my-mruby-simplehttpserver",
    "Date" => server.http_date,
  })
end

# 
# Location Configration
# 

# /mruby location config
server.location "/mruby" do |r|
  if r.method == "POST"
    server.response_body = "Hello mruby World. Your post is '#{r.body}'\n"
  else
    server.response_body = "Hello mruby World at '#{r.path}'\n"
  end
  server.create_response
end

server.run

iOSデバイスのIPをアドレス確認して、

http://111.111.111.111:8000

をブラウザに打ち込むと他のマシンでアクセスできるようになる。(エミュレータの場合はlocalhost:8000で同一マシン上の他のブラウザからアクセス可能)

mattn/mruby-sinaticみたいなWebアプリをさくっと書くための薄いラッパーがほしい。(mruby-uvがiOSでビルドできるならむしろmruby-sinaticも組み込んでしまうのがいいのかもしれない)

ブログが続かないので環境を整える

RubyPicoの開発日記を定期的に書きたいと思いつつ、なかなか続かないので環境を整備した。

デザインを変更

見た目が変わればやる気が増える。

CONTENTS - テーマ ストアがなかなかよかったので変更。

CONTENTSテーマはレスポンシブデザインに対応しているのでスマホのデザインも一緒に変わるのがありがたい。

カテゴリの整理

「エッセイ」、「テックログ」などのカテゴリが細かすぎて振り分けが難しかったのですべて「diary」にまとめた。

  • 基本はdiaryカテゴリで書く
  • rubypico, milkode など主題がはっきりしているものは専用カテゴリで書く

これで書くときにいちいちカテゴリ分けに迷わないようになった。

専用アプリ

ブラウザで書くと重いので専用アプリで書けるときは書く。

スマホはてなの公式アプリがあるのでそれを使う。

MacだとMochaというのがあるようなので今度試してみる。Windowsだと何がいいのかなあ。

mocha

mocha

  • Reo Hokazono
  • ライフスタイル
  • ¥120

書いた記事のSNSへの投稿

書いた記事をTwitterはてブ、Bufferなどに出すのが面倒なのでこの辺りはコマンドラインなどでそのうち自動化したい。

後は日記くらいならTwitterに1回投稿して終わるくらいにしておこう・・。

これでも買ってみますかね。

はてなブログ Perfect GuideBook

はてなブログ Perfect GuideBook

Milkode 1.8.9 リリース - キーボードショートカットがより便利に

ひそかに1.8.8もリリースしていたのですがブログ書いてなかったのでまとめて。

リリースノート

変更点

特に"ショートカットキーの s が押されると、ページトップにスクロール"と"相対URLモードで起動していると、ショートカットキー S による新タブ検索が行えない問題を修正"のおかげでショートカットキー(milk webを起動して[ヘルプ]->[キーボードショートカット])が大分使いやすくなりました。ぜひお試しください。

インストール

行指向のソースコード検索エンジンと検索アプリです。 数万オーダーのファイルから、目的のキーワードを含む1行を瞬時に検索することが可能です。

$ gem install milkode

http://milkode.ongaeshi.me/