Slide 1

Slide 1 text

素材の良さを活かしつつ、reST をReveal.jsに変換してみる話 by: Kazuya Takei on: 2018-11-28 in: SphinxCon JP 2018

Slide 2

Slide 2 text

話すこと 自己紹介 「reveal.jsに変換してみる」 「素材の良さを活かす」 変換で得た知見(3ケース) まとめ

Slide 3

Slide 3 text

Who am I?

Slide 4

Slide 4 text

Kazuya Takei Pythonista Errbotプラグイン/Errcron Ansibleロール @attakei Twitter/GitLab/GitHub NIJIBOX Co., Ltd サーバサイド領域主体(インフラがメイン) アーキテクト

Slide 5

Slide 5 text

「reSTをReveal.jsに変換してみ る」

Slide 6

Slide 6 text

Reveal.jsの特徴 HTMLを使ったプレゼンテーションツール 横だけでなく縦へのスライド進行 プラグインによる拡張 Markdownサポート PDF用のCSS reveal.js enables you to create beautiful interactive slide decks using HTML. — より https://revealjs.com

Slide 7

Slide 7 text

reSTをReveal.jsに変換するアプローチ raw:: html ディレクティブでゴリ押し(?) rst2reveal rst2slides sphinxjp.themes.revealjs

Slide 8

Slide 8 text

「素材の良さを活かす」

Slide 9

Slide 9 text

素材としてのreStructudedText Markdownより表現できるものが多い セクション管理ができる 「コメント」を書ける ディレクティブを自作して、表現の拡張が可能

Slide 10

Slide 10 text

器具としてのSphinx 普通に使っても、いい感じにHTMLを出力してくれる テーマの変更が容易 出力形式の拡張も容易

Slide 11

Slide 11 text

希望 reSTの文法をそのまま使えて 拡張ディレクティブの追加を最低限で済ませる を実現する Sphinx拡張(ビルダー, ディレクティブ, etc) Sphinxテーマ が欲しい

Slide 12

Slide 12 text

作ってみた Sphinx拡張 テーマ自体の内包はしている Sphinxのファイルを全部、それなりにいい感じのreveal.jsに変 換する sphinx-revealjs 0.3.1

Slide 13

Slide 13 text

特徴 reSTのセクション構造をそのままネストされたスライドにする reSTのコメントをスピーカーノートとする revealjs という別ビルダーにしたので、万が一普通のHTMLに したいときも阻害しない reST Sphinx H T M L r e v e a l j s

Slide 14

Slide 14 text

ここからは 実装時に出てきた「これをこうしたい」を元に、「reSTをこう活 用した」という事例をお送りします

Slide 15

Slide 15 text

活用1: コメントをスピーカーノ ートにせよ

Slide 16

Slide 16 text

reSTのセクション構造 .. This is comment With multiline

Slide 17

Slide 17 text

こうなって欲しい This is comment With multiline https://github.com/hakimel/reveal.js#speaker-notes

Slide 18

Slide 18 text

htmlビルドでの挙動 ※何も出ない

Slide 19

Slide 19 text

pseudoxmlにする This is comment With multiline

Slide 20

Slide 20 text

どうする? HTMLビルドでは、commentノードはまるごと無視している これを、reveal.jsのスピーカーノートに差し替える sphinx.writers.html5.HTML5Translator より def visit_comment(self, node): # type: (nodes.Node) -> None raise nodes.SkipNode

Slide 21

Slide 21 text

こうする SkipNode を投げなくすることで、中身をそのまま出せるよう にする visit_comment , depart_comment で中身を aside タグで囲 めばスピーカーノートの出来上がり def visit_comment(self, node: comment): self.body.append('\n def depart_comment(self, node: comment): self.body.append('\n')

Slide 22

Slide 22 text

難点 これだと、「本当にコメントアウトしたいこと」が消せなくな る 需要があるかはわからない revealjs_note みたいなディレクティブを作れば解決する 話ではある 今回は「ディレクティブを少なくする」を優先

Slide 23

Slide 23 text

活用2: コードブロックを Reveal.jsに合わせよ

Slide 24

Slide 24 text

reSTのセクション構造 .. code-block:: python def hello(): return 'world'

Slide 25

Slide 25 text

こうなって欲しい

def hello():
return 'world'
https://github.com/hakimel/reveal.js#code-syntax-highlighting

Slide 26

Slide 26 text

htmlビルドでの挙動

def return 

Slide 27

Slide 27 text

pseudoxmlにする def hello(): return 'world'

Slide 28

Slide 28 text

どうする? code-block は literal_block を作るのだが、中はそこそこ 複雑なことをしている reveal.js的には highlight.js に任せたいので、簡略化するの が一番速そう sphinx.writers.html5.HTML5Translator より def visit_literal_block(self, node): # type: (nodes.Node) -> None if node.rawsource != node.astext(): # most probably a parsed-literal bloc return BaseTranslator.visit_literal_b lang = node.get('language', 'default')

Slide 29

Slide 29 text

こうする やってることはスピーカーノートのときとおおむね同じ literal_block は language 属性を持つので、引き継ぐとよ い def visit_literal_block(self, node: literal_b lang = node['language'] self.body.append( f'
\n')

Slide 30

Slide 30 text

難点 pygments を捨てた highlight.js ⊂ pygemnts の場合、非対応言語が出たか も reveal.jsに寄せることを重視

Slide 31

Slide 31 text

活用3: セクション構造を Reveal.jsへ持ち込め

Slide 32

Slide 32 text

reSTのセクション構造 Title ===== Section 1. ---------- Content 1.1. ^^^^^^^^^^^^ Content 1.2. ^^^^^^^^^^^^

Slide 33

Slide 33 text

こうなって欲しい

Title

Section 1.

Section 1.1.

Slide 34

Slide 34 text

htmlビルドでの挙動

Slide 35

Slide 35 text

pseudoxmlにする Title

Slide 36

Slide 36 text

どうする? title から次の section までを section として囲んで、スラ イドにしたい docutils.writers._html_base.HTMLTranslator def visit_section(self, node): self.section_level += 1 self.body.append( self.starttag(node, 'div', CLASS='sec def depart_section(self, node): self.section_level -= 1 self.body.append('\n')

Slide 37

Slide 37 text

こうする section の入り際で「そのセクションの最初の子セクションに」 を仕切りとする def visit_section(self, node: section): self.section_level += 1 if self.section_level == 1: self._proc_first_on_section = True self.body.append('\n') return if self._proc_first_on_section: self._proc_first_on_section = False self.body.append('\n') self.body.append(f"\n") if has child sections(node, 'section'):

Slide 38

Slide 38 text

難点 ディレクティブ処理が若干入り組んでいる section ノードを明示的に指定する方法を探せてないため、 section に属性を追加するのが面倒 カスタムディレクティブでしのぎました

Slide 39

Slide 39 text

まとめ

Slide 40

Slide 40 text

振り返り Sphinxドキュメントを「なるべくそのまま」reveal.jsにするパッケ ージ作ってみた HTMLスライド用のビルダーが欲しいなら、HTML5用のビルダ ーをベースにできるので比較的楽 pseudoxmlがdocutilsの構造理解に便利 Sphinx/docutilsをちょっと理解できた気がする

Slide 41

Slide 41 text

参考資料など Sphinxドキュメント sphinxjp.themes.revealjs マスタリング docutils

Slide 42

Slide 42 text

ご清聴ありがとうございました