niszetの日記

細かい情報を載せていくブログ

(Pandoc) docx出力のテンプレートにある透かしはそのまま出力される(メモ)

一応確認できたのでメモだけ。

Wordファイル形式で出力する必要がある場合、テンプレートが準備されていることが多いのではと思います。

その際、透かしが入っているものが使えるのか?を今まで調べていなかったのですが、ちゃんと使えることを確認できたのでメモとして残しておきます。ただし、透かしにはフィールドコードをいれることが出来ないので、透かしの文字を変える必要があるならばその都度テンプレートのファイルを修正する必要があるので注意です。

ちゃんと意図したものになっているかは目視で確認した方が良いですね。 ヘッダやフッタはフィールドコードが入れられたと思うので、リビジョン等はそれで管理できるわけですが…悩ましい。

(Pandoc) 次のバージョンは2.8になりそう(メモ)

手元ビルドして気づいた。

Pandocはたまにマイルストーンが示されているのですが、そこを見るとバージョン番号が2.8に変わっています。

github.com

今回、かなり大きく変更が入っているので、納得感ありますが。残件10個。まだまだかかりそうですが…

何かしら貢献できるようになりたいなぁと思う次第です…

(Pandoc) Luaフィルタを書くときはコンストラクタの定義順に気を付ける(メモ)

Luaフィルタのマニュアルではわかりづらいのですが…

前回の記事でLuaのフィルタを書いていて実際に自分がハマったのでメモ。

Luaフィルタのマニュアルには各要素(BlockとかInlineとかのアレ。適切な訳語わからず)について、「Lua type reference」と「Module pandoc」2か所にわけて書かれています。前者が各要素が持つプロパティに相当するもの(これもなんていえばいいんだろう)とその説明。後者はモジュールに含まれている各要素のコンストラクタとしての使い方になります。

ここで、前の方に書かれている各要素の説明の順序とコンストラクタで定義するときの順序は異なります。これを間違えてもPandocはエラーを出さないことがあるので注意です。nilを与えるとエラーになったりするのですが…。正確な挙動は今ちょっとよくわからん…。

pandoc.org

Luaフィルタのマニュアルの読み方をまとめた方が良いかもしれないですねぇ…ダレカカイテ

(Pandoc) CodeをSpanに置き換えてスタイルをあてるLua filter

ただし、custom-styleがない場合はそのまま出力する。

Codeに対してもattributeをあてられるので、idとかclassとかattributesをつけられるので、こんな感じで、標準入力からpandocに送ってみる。今回使うのはcustom-styleのみだけども、idとかで処理を追加することも当然できる。

echo `r hoge`{.hoge .fuga #piyo poke=1.234 custom-style="ErrorTok"} `fuga` | pandoc  -f markdown -t docx --lua-filter code2span.lua -o test.docx

ここで、Luaフィルタはこんな感じで書けばよい。custom-styleを持つ場合のみSpanに置き換える。それ以外は何もせずに返す。

function Code (s)
  for k, v in pairs(s.attr.attributes) do
    if k == "custom-style" then
      x = pandoc.Span(s.text, s.attr)
      return x
    end
  end
  return s
end

出力はこんな感じ。

f:id:niszet:20191019221608p:plain

ErrorTokはコードハイライト時のエラー部分のテキストにあてられるスタイル。

自分以外に使い道ある人いなそうですが、備忘録として。

Enjoy!!

(Pandoc) Jira Writerを読む(自分用メモ)

これが一番シンプルなのでは?と思ったので。

docxは仕様が複雑なので、もっと簡単なファイルフォーマットでReader/Writerを学ぼうと思ったところ、最近追加されたJiraのWriterがわかりやすそうだったのでこれにした。Readerはまだない。

たぶん、ほかのtext系のファイルフォーマットでも良いと思う。docxみたいなバイナリ(といっても実態はxmlだが)を読むのはやめよう。あれは沼。あれは闇。あれは全てを飲み込む狂気の形式。。。

JiraのWriterのコードはここにある。

github.com

これを読む前に、Pandoc's native ASTについてはある程度理解している必要がある。ここでは説明しない。

あと、Haskellの基本的な文法もある程度さらっている必要がある。具体的な処理がわからなくても、モナドってなんだっけ…もにゃもにゃ…くらいのことはわかってないと当然読めない。これもここでは説明しない。なぜなら説明できるほどわからないから。

というわけで、多分間違ってる箇所があるのだが、Haskellは難しいしPandocのコードは長いしで、ちゃんと理解してから書こうとするといつまでも書けないのでとりあえず、読んだ記録ぐらいのつもりで書く。なので、あまり参考にならないししないでくださいな。

module Text.Pandoc.Writers.Jira ( writeJira ) where ... から、このモジュールからはwriteJiraだけが外に出ていることがわかる。つまり、ほかの関数は中で自由にしている。ただし、ほかのファイルを読むと同名の関数が定義されていたりするので、必要な処理はどの形式でもおおむねかわらないのではということがなんとなーく見れる。

肝心のwriteJiraはこんな感じの定義。

writeJira :: PandocMonad m => WriterOptions -> Pandoc -> m Text
writeJira opts document =
  evalStateT (pandocToJira opts document) startState

WriterOptionsPandoc を受け取っているが、PandocLuaで扱ったとき、documentのtop階層だったはずなので、たぶんそれ。実体もdocumentってなってるので多分。ここで、Textは import Data.Text (Text, pack) のTextだろう。

で、pandocToJiraは直後に定義がある。

pandocToJira :: PandocMonad m
             => WriterOptions -> Pandoc -> JiraWriter m Text

ここで、JiraWriter

type JiraWriter = StateT WriterState

とあって、

data WriterState = WriterState
  { stNotes     :: [Text]      -- Footnotes
  , stListLevel :: Text        -- String at beginning of list items, e.g. "**"
  }

とあるので、状態を持ちながら、Writerのオプションと文書を受け取ってPandocMonad Textを返している、というなる、のかな?ということは、ファイルへの書き出しはここではしておらず、あくまでPandoc's ASTをうけとって、Jiraの形式に変換して返しているのだろうということになりますね。

他に、escapeCharForJira :: Char -> TextescapeStringForJira :: Text -> Textから、エスケープするべき文字を変換していることがわかり、メインの変換処理はblockToJirablockListToJirainlineListToJirainlineToJiraで行っていて、Listの入っているものはmapMでListなしの関数を呼び出して処理、それぞれの処理は要素毎に定義してある、ということが見て取れる。つまり、Pandoc's ASTのすべての型に対して、blockToJirainlineToJiraの処理を書き、それのList版を書き…とやっていけばよいということがわかる。

あとは補助関数っぽいので、これらはフォーマットごとに違うだろう。

あとはstateがどのようにふるまっているのかが追い切れていないのでいずれ読む…のと、個別の関数の挙動が(Haskellの理解が浅いために)把握しきれていないので、これを順次追いかけていく予定…。

ということで、Pandoc's ASTを把握したら次はWriterを見てみるのが良さそう、という考えは良さそうです。

概略がわかれば、あとはひとつひとつ追っていけばよいので気が楽ですね(楽ではない)

という、メモでした。

技術書典7で入手した技術同人誌の感想置き場

恒例の。

まぁもはやどのタイミングで入手したのかわからなくなってきましたけどね。

1~

11~

技術書典7に一般参加してきました。

久々の一般参加です。

前回、前々回はサークル参加だったので、一般参加は1年以上ぶりになります。今回は初の会場が2フロアあるという今までで一番大きな回となってました。

私は11時からのチケットを購入して、10:50~くらいに並びましたが入れたのは11:30くらいで、40分くらい並んだことになりますね。今日は日差しが強く(昨日に比べ)、日向にいると結構厳しいのですが、待機列は日影となる場所にいる時間が長かったのでそこまで大変ではなかったです。夏コミのときもそうだけど、何かしら日差しを遮るものが必要ですね。コミケだと待機列で日傘NGでしたが、今回は特に注意されていないようでした。私はとりあえずタオルをあたまにかけてました。見栄えより機能重視ということで。

戦利品はなんか60cmくらいあるんですが、まぁそれはいつも通りなので良いかな。

今回、フロアが分かれていてジャンルが分かれていた関係で主に2階で色々物色しました。毎回、前日にサークルチェックしていくのですが、それでも当日見つけられなかったり、抜けてたり、軍資金が足りなかったり体力がなくなったりで思った通りには行かないのですが、それでも大部分を入手できたので良かったです。読もう。もう2冊読んだけど。まだまだたくさんある。感想はまた別の記事にします(Twitterの投稿を張り付けるだけ)

やはりフロアをまたぐ運用は混乱がちょっとあったようで、どこから2F<->3Fへ抜けるのかはぱっと見ではわからなかったかもですね。あと、3Fに行く列が結構並んでてそれが精神的にブレーキになったかもしれないですが、実際はサクサク移動できたので、あれは待機列をあまり伸ばさずに、すぐに行けると思わせる方が良かったかもしれないですね。いやそもそもあそこで移動とわかってない人はいたみたいなんだけど。ただ、導線を考えると今回の動き方は良かったと思うので、次回以降またよくなるんじゃないかな。技術書典は毎回良くなっていくってイメージが持てるのはよいですね。それ以上に規模が拡大しているのだけど。

混雑度は、やはり2F入り口がちょっと混雑し気味で、うまく流れにくい感じがありましたね。なので、一旦そこを抜けてしまうと戻るのが難しい…。トートバックを最後に買う力がなかった…。

それ以外は結構制御された混雑だったので、そんなに混乱はなかったのでは。アナウンスはあまり聞き取れなかったかなぁ。まぁ難しいっすね…。

あと、後払いのやつは前日にでもアカウント作っておかないとダメっすね…。今回、後払いのみのところで購入できなかった…。痛恨のミス…。まぁ、電子版とかもあるのでそこに期待しよう…。

最終的に15:30くらいまでいたので、割といろんな知り合いに声をかけることができたのが良かったですね。とはいっても混んでる間はあまり話せないので、それが出来たのは14時以降かな…。あまり長時間滞在できない人は2言3言がせいぜいか。まぁこれも規模で決まってしまうからなぁ…。

さて、今回はサークル参加見送ってしまいましたが、今回またやる気をチャージしたので次回、チャンスがあればサークル参加で臨みたいですね。今回もとても楽しかったです。