CodeBlockまわりが面倒くさい…
さて、前回の続きです。CodeBlock周りの扱いをどうにかしないといけないのですが…長くなりそうなので複数回にまたがる予定です。
前回の記事にも訂正を入れましたが、docxからMarkdownに変換する際、スタイルがSource Code
になっているものはCodeBlock
になっていない、というのは間違いで、ちゃんとCodeBlock
となっています。これは、-t native
等で変換すれば確認できます。
しかし、backtick_code_blocks
が効かないのはなぜかという疑問が残ります。
これは実際にMarkdown Writerのコードを読めばわかります。
以下、コード引用。。。
blockToMarkdown' opts (CodeBlock attribs str) = return $ case attribs == nullAttr of False | isEnabled Ext_backtick_code_blocks opts -> backticks <> attrs <> cr <> literal str <> cr <> backticks <> blankline | isEnabled Ext_fenced_code_blocks opts -> tildes <> attrs <> cr <> literal str <> cr <> tildes <> blankline _ -> nest (writerTabStop opts) (literal str) <> blankline
これを見ると、attributeがnullの場合はisEnabled Ext_backtick_code_blocks opts
を見てくれないことがわかりますね。つまり、属性ナシのCodeBlockはindented code blockになるということです。
実際、前回の出力を見てもCodeBlockはインデントされた状態で書かれていましたが、あれが素のCodeBlockとして必要十分ということでした。
なので、docxに再変換するとSourceCodeになります(たとえ-f docx+styles
から変換したmarkdownファイルでなくても)
しかし、r
などの言語の指定がないので素のコードになります。
また、再変換時は最初に変換したときと同じように --highlight-style tango
をつけてあげないと仮に言語の指定があっても再生成したdocxと初めに生成したdocxは等価にはなりません。注意。
pandoc word.docx -t markdown+fenced_code_blocks+fenced_code_attributes -o word_nowrap.md -f docx --atx-headers --wrap=none --extract-media=hoge --highlight-style tango
Lua filterの力を借りる。
ということで、docxからは正しくCodeBlockに変換されるけども、docxに生成した時点で言語情報が失われているので生成したmarkdownのCodeBlockはインデントつきのコードブロックになってしまうのでした。
ということは、Pandocデータ構造(Pandoc's AST)に変換されたあと、CodeBlockに対して言語情報を付与すれば、backtickやfenced codeの形に出来そうだということです。
ということで、まずお試しのコードを作ります。こんな感じ。
function CodeBlock(e) e.attr = {class ="r"} return(e) end
attrの与え方はマニュアルを参照。
これをcodeBlock.lua
というファイル名にしたとして、markdownへ書き戻し、
pandoc word.docx -t markdown -o word_rev.md -f docx+styles -s --atx-headers --wrap=none --extract-media=hoge -L codeBlock.lua
すると、すべてのCodeBlockにrというclassが付与されます。
--- author: niszet date: 2020/5/20 title: word --- ## R Markdown ::: {custom-style="First Paragraph"} This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see [[http://rmarkdown.rstudio.com]{custom-style="Hyperlink"}](http://rmarkdown.rstudio.com). ::: ::: {custom-style="Body Text"} When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this: ::: ::: {custom-style="Source Code"} \``` {.r} summary(cars) \``` ::: ::: {custom-style="Source Code"} \``` {.r} ## speed dist ## Min. : 4.0 Min. : 2.00 ## 1st Qu.:12.0 1st Qu.: 26.00 ## Median :15.0 Median : 36.00 ## Mean :15.4 Mean : 42.98 ## 3rd Qu.:19.0 3rd Qu.: 56.00 ## Max. :25.0 Max. :120.00 \``` ::: ## Including Plots ::: {custom-style="First Paragraph"} You can also embed plots, for example: ::: ::: {custom-style="Body Text"} ![](hoge/media/rId23.png){width="5.0526312335958in" height="4.0421052055993in"} ::: ::: {custom-style="Body Text"} Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot. :::
あとは再度docxに変換すればよいのです
pandoc -o word_rev.docx -f markdown word_rev.md -t docx --highlight-style tango
が、この通りやると、元々Rのコードでない部分もあわせてRのコード扱いになってしまい、等価ではなくなります。つまり、一度docxに変換してしまうと元のコードが何だったのか知るすべがないということですね。
なので、これに対応するためには、docx出力時に生成されるCodeBlockに対して細工をしておく必要がありそうです。例えば、スタイルをSource Code hoge
のような名前にして、hogeにその言語名を入れるなどです。
ただし今度はdocxから書き戻す際に、Readerはこれを無視するので、Divでcustom-styleがSource Code hoge
である場合はCodeBlockにclass hogeを与えたものを生成するようなフィルタが必要となります。
つまり、
- md -> docx でCodeBlockをDivに置き換えるLF
- 対応するスタイルを指定したreference.docx
- docx -> md でDivをCodeBlockに置き換えるLF
の準備が必要…ということになりますね。面倒ではありますが…。docx -> docx をかませる方法もありますが…(スタイルを置き換える処理などはそのまま残りますが...)
ということで、ちょっと手間が増えるのでやるかどうかは不明ですが、一応道筋はみえてきたかなと。
さて、ほかの課題も見ていかねばなので、続きはまたある程度結果がまとまった時に。