2012/08/24


microformats 正直、microformatsは勉強してませんでした。
twitterでotsune氏がよく「microformats」についてコメントさえておられたのを聞いて、私もmicroformatsについて勉強しなきゃと少しだけですが勉強してみました。

microformatsとは?

microformatsとは、Web上にメタデータを付与し、言わば添付データとして二次利用可能なデータを指しています。
最近ではTechnoratiが盛んに注目しており、検索しようとしている人に対するマッチングに利用しようとしているみたいです。

microformatsを扱う上で何か覚えなくてはならないのか?

いえ、microformatsは現存のHTMLに対するクラス名、リンク属性の指定方法を特定の決まりに従い設定する事でそれをmicroformatsとして扱わせるものです。
ですから、現状の既に書いていたHTMLが実はmicroformatsに対応していた...なんて事もあるかもしれません。

microformatsで何が出来るのか?

詳しくはmicroformatsのオフィシャルサイトで確認して頂きたいのですがmicroformatsとして添付出来るデータの種別は以下の通りです。
  • hCalendar
  • hCard
  • rel-license
  • rel-nofollow
  • rel-tag
  • VoteLinks
  • XFN
  • XMDP
  • XOXO
と多種に渡ります。例えばhCalendarにはイベント等を添付する事ができ、Webサイトを閲覧したユーザにイベント告知をする事も出来ます。
また、hCardはブログ等の記者、もしくはレビューワの身元情報を添付する事ができ、Webサイトを閲覧したユーザに連絡先を教える事が出来ます。

microformatsて実際どんなの?

このサイトのHTMLを見て下さい。
(HTML Validatorでエラーがいっぱい出るのは無視して下さい)
HTMLの中で「<!-- microformats」を検索してみて下さい。
コメントの「start」から「end」までがmicroformatsとなります。 <!-- microformats 'hCard' start -->
<div id="hcard-Yasuhiro-Matsumoto" class="vcard" style="display: none;">
  <img style="float:left; margin-right:4px" src="http://mattn.kaoriya.net/images/logo.png" alt="photo" class="photo"/>
 <span class="nickname">mattn</span>,
 <a class="url fn" href="http://mattn.kaoriya.net">MATSUMOTO Yasuhiro</a>

 <a class="email" href="mailto:mattn.jp[at]gmail.com">mattn.jp[at]gmail.com</a>
 <div class="adr">
  <span class="country-name">japan</span>
 </div>
</div>
<!-- microformats 'hCard' end -->
これがhCard情報になります。
Microformats Bookmarkletで確認すると

microformats_bookmarklet

とこのサイトの作者情報が表示されます。(bookmarklet)
追記:名前を少し書き換えました。
また記事1件に対して1個ずつ以下のmicroformatsも追加してあります。 <!-- microformats 'xFolk' start -->
<div class="xfolkentry" id="xfolkentry-20070801190741" style="display: none;">
  <a class="taggedlink" href="http://mattn.kaoriya.net/software/linux/vim/20070801190741.htm">意外と知られていないvimのtips(calendar.vimの日記機能をGoogle Calendarと同期させる)</a>
</div>
<!-- microformats 'xFolk' end -->
これにより、記事1件に対してxFolk形式のmicroformatsが埋め込まれます。
こちらは、上記Microformats Bookmarkletでは確認出来ませんが、以下に示すmicroformats Operatorで確認出来ます。

microformatsを体験するにはどうしたらよい?

まず、Firefoxブラウザをお使いならばmicroformats Operatorを入れてOperatorツールバーでPermaLink一覧が表示されます。

microformats_operator_toolbar

このmicroformats Operatorでは各種microformatsが閲覧できたり、それに対するActionを設定出来ます。
例えばPermaLinkに対してSBMへ登録するメニューを設定したり、hCardをvCardファイルへ保存する事も出来ます。

まとめ

microformatsの可能性として、今後上記スキーマを利用したサードパーティアプリケーションが増えて来る事が想像出来ます。microformatsはHTMLに特化したものではなく、Feedに適応する事も出来ます。
言わばデジタル放送のサブストリームのようなイメージですね。デジタル放送でも本放送のサブストリームとしてニュースや番組情報を流したりしています。
スキーマも拡張可能なようですから、拡張次第ではCGI側ではてなブックマークコメントを流したりする事も出来るでしょう。

おまけ

今回microformats OperatorのActionとして、はてなブックマークActionを作成してみました。

ダウンロード:
注意:microformats Operator version 0.8b上で動作します。

これをmicroformats Operatorの「Options」画面の「User Scripts」タブから読み込み、「Actions」タブで「New」をクリックすると「Bookmark with Hatena Bookmark」が選択出来るようになります。

microformats_operator1

これでxFolkメニューから表示されるようになります。

microformats_operator2

後はそこに出てくる「Bookmark with Hatena Bookmark」を選択すると

microformats_operator3

とはてなブックマーク登録画面に遷移します。
よかったらmicroformatsの勉強にお役立て下さい。

また、個人的なまとめなので間違ってたらご指摘下さい。

リンク

microformats.org
Technorati Kitchen
microformats Operator


mattn the micromagick!
Posted at by




Rietveld 先日、golangに3件不具合修正を行った。
その際、golangにはpatchを提供する際に、コードレビューをしてもらうのだけど、それに使用しているrietveldが素晴らしく良かった。
rietveldはGoogle App Engineのサーバ上で動作し、クライアントから使うにはmercurialが必須となる。hgrcファイルに以下の修正を追加する。
[extensions]
codereview = YOUR_GO_ROOT/lib/codereview/codereview.py
次にcodereview.appspot.comへログインする。 # hg code-login
Email (login for uploading to codereview.appspot.com): rsc@golang.org
Password for rsc@golang.org:

Saving authentication cookies to
/Users/rsc/.codereview_upload_cookies_codereview.appspot.com
これで準備完了。
golangのリポジトリ上で最新を得て、修正を行った。ここでcommitはしなくて良い。 # hg changes
するとエディタが起動して以下の入力を求められる。
# Change list.
# Lines beginning with # are ignored.
# Multi-line values should be indented.

Reviewer:
CC:

Description:
    <enter description here>

Files:
    src/pkg/math/sin.go
    src/pkg/math/tan.go
    src/pkg/regexp/regexp.go

内容を記入して保存終了する。これでcodereview.appspot.comにissueとして登録される。
放っておくと、レビューワが修正を確認してくれる。
ダメ出しを貰った際には、再度修正し以下のコマンドを実行。
# hg mail レビュー受付番号
これだけ。
次に修正しても同じコマンドを実行するだけ。ちなみに別の修正対象ファイルで複数のレビューをお願いする場合は、「hg changes」の引数に変更したファイルを指定すれば良い。あとは個別に「hg mail」の受付番号を指定すれば良い。
ちなみにmailとあるが、メールを送る訳ではなくcodereviewシステムに送られるだけなので、http/httpsポートが開いていれば使える。

結構便利。

ちなみに3件送った修正の内、2つは取り込まれそうです。
取り込まれると、ココに名前が載せてもらえるらしいので少しワクワク。

あと、rietveld自身は以下のサイトからダウンロード出来る。
rietveld - Project Hosting on Google Code

This project shows how to create a somewhat substantial web application using Django on Google App Engine.

http://code.google.com/p/rietveld/
Google App Engineはpythonのバージョンが2.5だし、rietveld自身はDjango1.0でしか動かないので、virtualenvを使うのが良いと思う。
Posted at by




これは嬉しい!Growl for Windowsの2.0 BETAがリリースされています。

これまではGoogle Codeにあるプロジェクトの物を使っていましたが、どうやらこれの正式版がリリース(とは言ってもBETAですが)されていました。
試しにこれまでのコードで試してみてもNetGrowlであれば問題なく動作しました。
そして気になっていたアイコンですが...

出るようになっています!

ただ、MacのGrowlの様にMac専用のインタフェースを使っているのではなく、TCP/IP接続による独自プロトコルGNTPを使っています。

ちょっと調べた感じだと、簡単なソケット通信で実現出来そうだったので適当ですがコマンドラインプログラムを作ってみました。
/**
 * msvc: cl growlc.c
 * mingw32: gcc -o growlc.exe growlc.c -lws2_32
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <locale.h>
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib")
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif

static void sendline(int sock, const char* str, const char* val) {
    int len = strlen(str);
    char* line;
    if (val) {
        len += strlen(val);
        line = (char*) malloc(len + 3);
        strcpy(line, str);
        strcat(line, val);
        strcat(line, "\r\n");
    } else {
        line = (char*) malloc(len + 3);
        strcpy(line, str);
        strcat(line, "\r\n");
    }
    send(sock, line, len + 2, 0);
    free(line);
}

static char* recvline(int sock) {
    const static int growsize = 80;
    char c = 0;
    char* line = (char*) malloc(growsize);
    int len = growsize, pos = 0;
    while (line) {
        if (recv(sock, &c, 1, 0) <= 0) break;
        if (c == '\r') continue;
        if (c == '\n') break;
        line[pos++] = c;
        if (pos >= len) {
            len += growsize;
            line = (char*) realloc(line, len);
        }
    }
    line[pos] = 0;
    return line;
}

int create_socket() {
    int sock = -1;
    struct sockaddr_in serv_addr;
    struct hostent* host_ent;
    char value = 1;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("create socket");
        printf("%d\n", WSAGetLastError());
        return -1;
    }

    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));

    if ((host_ent = gethostbyname("127.0.0.1")) == NULL) {
        perror("gethostbyaddr");
        return -1;
    }
    memset((char *)&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    memcpy(&serv_addr.sin_addr, host_ent->h_addr, host_ent->h_length );
    serv_addr.sin_port = htons((short)23053);

    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("connect");
        return -1;
    }
    return sock;
}

static void close_socket(int sock) {
#ifdef _WIN32
    if (sock < 0) closesocket(sock);
#else
    if (sock < 0) close(sock);
#endif
}

static char* string_to_utf8_alloc(const char* str) {
#ifdef _WIN32
    unsigned int codepage;
    size_t in_len = strlen(str);
    wchar_t* wcsdata;
    char* mbsdata;
    size_t mbssize, wcssize;

    codepage = GetACP();
    wcssize = MultiByteToWideChar(codepage, 0, str, in_len,  NULL, 0);
    wcsdata = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
    wcssize = MultiByteToWideChar(codepage, 0, str, in_len, wcsdata, wcssize + 1);
    wcsdata[wcssize] = 0;

    mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsdata, -1, NULL, 0, NULL, NULL);
    mbsdata = (char*) malloc((mbssize + 1));
    mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsdata, -1, mbsdata, mbssize, NULL, NULL);
    mbsdata[mbssize] = 0;
    free(wcsdata);
    return mbsdata;
#else
    return strdup(str);
#endif
}

int main(int argc, char* argv[]) {
    int sock = -1;
    char* title = NULL;
    char* message = NULL;
    char* icon = NULL;
#ifdef _WIN32
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) goto leave;
    setlocale(LC_CTYPE, "");
#endif

    if (argc != 3 && argc != 4) {
        fprintf(stderr, "%s: title message [icon]", argv[0]);
        exit(1);
    }

    title = string_to_utf8_alloc(argv[1]);
    message = string_to_utf8_alloc(argv[2]);
    if (argc == 4) icon = string_to_utf8_alloc(argv[3]);

    sock = create_socket();
    if (sock == -1) goto leave;
    sendline(sock, "GNTP/1.0 REGISTER NONE", NULL);
    sendline(sock, "Application-Name: My Example", NULL);
    sendline(sock, "Notifications-Count: 1", NULL);
    sendline(sock, "", NULL);
    sendline(sock, "Notification-Name: My Notify", NULL);
    sendline(sock, "Notification-Display-Name: My Notify", NULL);
    sendline(sock, "Notification-Enabled: True", NULL);
    sendline(sock, "", NULL);
    while (1) {
        char* line = recvline(sock);
        int len = strlen(line);
        /* fprintf(stderr, "%s\n", line); */
        free(line);
        if (len == 0) break;
    }
    close_socket(sock);

    sock = create_socket();
    if (sock == -1) goto leave;
    sendline(sock, "GNTP/1.0 NOTIFY NONE", NULL);
    sendline(sock, "Application-Name: My Example", NULL);
    sendline(sock, "Notification-Name: My Notify", NULL);
    sendline(sock, "Notification-Title: ", title);
    sendline(sock, "Notification-Text: ", message);
    if (icon) sendline(sock, "Notification-Icon: ", icon);
    sendline(sock, "", NULL);
    while (1) {
        char* line = recvline(sock);
        int len = strlen(line);
        /* fprintf(stderr, "%s\n", line); */
        free(line);
        if (len == 0) break;
    }
    close_socket(sock);
    sock = 0;

leave:
    if (title) free(title);
    if (message) free(message);
    if (icon) free(icon);

#ifdef _WIN32
    WSACleanup();
#endif
    return (sock == 0) ? 0 : -1;
}
mingw32でもMSVCでもビルド出来るかと思います。サンプルとしては第一引数から、タイトル、メッセージ、アイコン(省略可能)となっています。
アイコンは、Growl本体側が取得してくれるようなので例えば C:¥> growlc パンが焼けました 黒焦げです http://mattn.kaoriya.net/images/logo.png
とすると
growl4windows-example
といったGrwolが表示されます。

すばらしいですね!
黒焦げですね!

あとはMacのGrowlとWindowsのGrowlが抽象化される様なレイヤが揃えば、Growlを使ったマルチプラットフォームなアプリケーションが作れる様になりますね。
Posted at by