2021-08-05 ,

org-modeをData URI Schemeに対応させる

とりあえず対応させてみました。

↓はData URIなんですけど表示されてますか?

赤い丸(SVG)
図1: 赤い丸(SVG)
富士山!(JPEG)
図2: 富士山!(JPEG)

↑の書き方(org-modeのソース)は次の通りです。

#+CAPTION: 赤い丸(SVG)
[​[data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTAwIiB3aWR0aD0iMTAwIj4NCiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iNDAiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMyIgZmlsbD0icmVkIiAvPg0KPC9zdmc+DQo=]]

#+CAPTION: 富士山!(JPEG)
[​[data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAeAAD/7gAOQWRvYmUAZMAAAAAB/9sAhAAQCwsLDAsQDAwQFw8NDxcbFBAQFBsfFxcXFxcfHhcaGhoaFx4eIyUnJSMeLy8zMy8vQEBAQEBAQEBAQEBAQEBAAREPDxETERUSEhUUERQRFBoUFhYUGiYaGhwaGiYwIx4eHh4jMCsuJycnLis1NTAwNTVAQD9AQEBAQEBAQEBAQED/wAARCAAyAGQDASIAAhEBAxEB/8QAgAAAAgMBAAAAAAAAAAAAAAAAAAMBAgQFAQADAQEBAAAAAAAAAAAAAAAAAQIDBAUQAAEDAgQDBQYFBQAAAAAAAAEAAgMRBCExQRJRYQVxgcEiE/CRoTJCI9FighQGsVJy0hURAAICAQUBAQAAAAAAAAAAAAABEQIhMUFxEgNhIv/aAAwDAQACEQMRAD8A3UUUTdqjavTk4RdEbUyiCESAvaooupadIkkHq3NYos9uTz/qtEsdrb27nmNvosxNBUuP0tbriVm/aqcL9cGi821LwcOmuiKLbYRsuZWzOFHuJLmfTUHIjgFlvz+1vZWBpNuTVnFoOnv0VL0Tt10ZLpCkXRFFdhZI3cw7hy8VO1XJIuiKJm1RtSkYuiEzahEgP2oppqcgujH0xxP3JABwYKn4pzH9Ptdwic3e2geR55MchgsLeyWn6LXm3rgxQdMuZaFwETDjV3zU/wAfxXStrG3tjuY3fIM5X+A0WC6/kNnECIj6zxlo2vMrmTfyK4kG07RGHCtBSrRiQeTslm36X+I0SrX6zvz3QeKM8zjXZ/aKYbnDXksPUqMsXNc5xeW9ri0GrqcOSLa7bJbC8lpFGRvcTjQDCpp8Fnml/emR0cgMM3kYW4kNaKf1xRWsPgbeOSttIYLtkjDSCaIFjnUFZCK4/mcnXVsJ9gFXCRo81RUO4HvzWQPt/wB62IncyGNkcUTfMXStzw4N1KnqN3Pbwhsbmm4jf6jY8Hbg75wOzNVuo1J2yZ32jo/uxbo5AS1zW4iozpXPsVhO5jWm4ZRrhhKzFv6hm1DOrCS29a5YXMeNskrRSrqV2kYeamoTY7m1lkMDHje5m9ocKB7TjjzotFd7ol1WxZu17dzCHNOoxCNqqLSMOJjJilpVpYaB1eNcCUmPqMBO18jX/mb5T3tPgq7Jk9WP2oR69tt3eo2iESEHMuuuTTuqS5wGFK+mwgalrfMa8ysU3ULqYU3emzSOIbG/DE96zjHPAozyxUqqWxTbJLzqUBzndgUGmqN3AYJiN111B/8Az4bGJ3kA3SvIoXGtdvYCskE8kIcYnFsjsNwz20xAPNUNCa1FSpa0AgjHgUsIeWaIb2W39F8IAfG1zXOI3Fwca0x0WaaaWaUzSuL5XUJec/grUaRiFDgKcxqhQGSwvJjEYH/ciOJa7Q8WnQpkVw5txFdOJl9LbRoIaQW5B3LsWanvUhrgQ4dyMCya7vqdzckZQxjFsTK0B1OKyGutVYgUrka5ckbTSoIPfihQMrsbtrTmhFDWuqEAW+p2eff3oOXt8EIQIjUeKDl3IQgZQ5J306+KEJMELf8AKc/1I4exQhADOHjn3KW/j2IQkUU+kZ69in2xQhMRX3IQhAj/2Q==]]
Emacs上での見た目
図3: Emacs上での見た目

Data URIを使うとorg-mode文書のサイズが肥大化するのと引き換えに外部ファイルを管理する手間が省けたりします(こうやってエクスポートしてWeb上に上げた場合はHTTPリクエストが減るとか、一方で画像キャッシュが効かないとか色々あると思います)。

Web上を検索したらorg-modeとData URIに関する話題はチラホラ見かけたのですがそのものズバリというものは見つからなかったんですよね。同じ事を考える人は沢山いそうなのですが……。

ソースは次の場所に置きました。

misohena/org-inline-image-fix: A collection of fixes related to the image display feature in org-mode

が、かなりヤバイクソコードなのでご了承ください。

インライン画像表示まわりは例によって org-display-inline-images 関数にadviceをかけて実現しているのですが、この関数は元々結構長くて改造が容易ではありません。以前は丸丸上書きするような修正の仕方もしたのですが、org-mode側に修正が入ると直さなければならなくなるので面倒です(ちょっと前にリモート画像対応が少し入りました)。なので今回は極力元の関数を活かす方向で修正したのですがそれが悪夢の始まりでした。

長ったらしい関数の中の挙動を修正するにはそこから呼び出す関数を書き替えるしか手が無く、 cl-letf で沢山の関数を上書きして無理矢理実現しています。まるで針の穴を通すようなプログラミングにゾクゾクしてしまいました。まるでパズルゲームです。何度もこれはもうダメか、書き直すしか無いかと諦めかけました。 org-element-property が実は defsubst でバイトコンパイルがかかると呼び出されないということに気がついたときにはどうしようかと思いました。追い詰められて plist-get とか format とか基本的な関数を書き替えているのでどこでおかしくなるか分かりません。 org-display-inline-images を書き替える他のプログラムを使ったときの動作は保証いたしかねます。正直全部上書きした方がまだマシだったかもしれませんね。どうせorg-mode側で修正がかかったら全部おじゃんでしょう。

:after adviceをかけて、本家の処理が終わった後にもう一度バッファを走査するのが一番安全かもしれません。大きな文書では効率が落ちるかもしれないので今回は回避しましたが(画像を扱っている時点で今更?)。

YouTube動画へのリンクを画像に置き換えるコード(TobiasZawada/org-yt: Youtube links in org-mode)を見つけたのですが、それは:afterアドバイスで再走査していました。皆さん苦労しているようです。

私も今 org-display-inline-images には三つもアドバイスがかかっているので苦労しています(上のリポジトリにはこれまでのものをまとめてあります: URLリンク対応, 画像リンク即時表示, サイズ制限)。

元々のコードがもう少し改造しやすくなっていると良いのですが……。

あ、あとエクスポートはHTMLだけ対応ですのであしからず。こちらも面倒でした。

Pingback / Trackback

  • […] 通常のリンク形式(file, http, https)を拡張することも考えたのですがData URI対応の経験から既存の処理と混ざると非常に面倒だと思ったのでひとまず完全に独自のリンクタイプとしました。gzipで圧縮したSVGはブラウザで直接表示できないので、どのみちエクスポート時には独自の変換処理が必要になります。将来的には.edarw.svgファイルへの通常リンク(例: [​[file:./example.edraw.svg]] )を直接編集できるようにすることも考えています。ただ、データをorgファイル内に埋め込みたいと思うならやはり独自形式の方が都合が良いと思います。 […]