Upgrade to Pro — share decks privately, control downloads, hide ads and more …

素材の良さを活かしつつ、reST をReveal.jsに変換してみる話 / Converting pure reST to Revealjs

252e6c31a6452aa80deb9ad0107975c7?s=47 attakei
November 28, 2018

素材の良さを活かしつつ、reST をReveal.jsに変換してみる話 / Converting pure reST to Revealjs

SphinxCon JP 2018 のトーク枠で発表した、内容のPDF版です。

オリジナル版はReveal.jsのスライドとなっており、現在は以下のURLで公開されています。
https://attakei.gitlab.io/slides/talks/sphinxcon-jp-2018/

252e6c31a6452aa80deb9ad0107975c7?s=128

attakei

November 28, 2018
Tweet

Transcript

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

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

  3. Who am I?

  4. Kazuya Takei Pythonista Errbotプラグイン/Errcron Ansibleロール @attakei Twitter/GitLab/GitHub NIJIBOX Co., Ltd

    サーバサイド領域主体(インフラがメイン) アーキテクト
  5. 「reSTをReveal.jsに変換してみ る」

  6. Reveal.jsの特徴 HTMLを使ったプレゼンテーションツール 横だけでなく縦へのスライド進行 プラグインによる拡張 Markdownサポート PDF用のCSS reveal.js enables you to

    create beautiful interactive slide decks using HTML. — より https://revealjs.com
  7. reSTをReveal.jsに変換するアプローチ raw:: html ディレクティブでゴリ押し(?) rst2reveal rst2slides sphinxjp.themes.revealjs

  8. 「素材の良さを活かす」

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

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

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

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

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

    M L r e v e a l j s
  14. ここからは 実装時に出てきた「これをこうしたい」を元に、「reSTをこう活 用した」という事例をお送りします

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

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

  17. こうなって欲しい <aside class="notes"> This is comment With multiline</aside> https://github.com/hakimel/reveal.js#speaker-notes

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

  19. pseudoxmlにする <comment xml:space="preserve"> This is comment With multiline

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

    (nodes.Node) -> None raise nodes.SkipNode
  21. こうする SkipNode を投げなくすることで、中身をそのまま出せるよう にする visit_comment , depart_comment で中身を aside タグで囲

    めばスピーカーノートの出来上がり def visit_comment(self, node: comment): self.body.append('<aside class="notes">\n def depart_comment(self, node: comment): self.body.append('</aside>\n')
  22. 難点 これだと、「本当にコメントアウトしたいこと」が消せなくな る 需要があるかはわからない revealjs_note みたいなディレクティブを作れば解決する 話ではある 今回は「ディレクティブを少なくする」を優先

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

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

  25. こうなって欲しい <pre><code class="python"> def hello(): return 'world'</code></pre> https://github.com/hakimel/reveal.js#code-syntax-highlighting

  26. htmlビルドでの挙動 <div class="highlight-python notranslate"> <div class="highlight"> <pre> <span></span> <span class="k">def</span>

    <span class="n <span class="k">return</span> <span c </pre> </div> </div>
  27. pseudoxmlにする <literal_block force_highlighting="True" highlight_args="{}" language="python" linenos="False" xml:space="preserve"> def hello(): return

    'world'
  28. どうする? 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')
  29. こうする やってることはスピーカーノートのときとおおむね同じ literal_block は language 属性を持つので、引き継ぐとよ い def visit_literal_block(self, node:

    literal_b lang = node['language'] self.body.append( f'<pre><code data-trim data-noescape def depart_literal_block(self, node: literal_ self.body.append('</code></pre>\n')
  30. 難点 pygments を捨てた highlight.js ⊂ pygemnts の場合、非対応言語が出たか も reveal.jsに寄せることを重視

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

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

    1.2. ^^^^^^^^^^^^
  33. こうなって欲しい <section> <h1>Title</h1> </section> <section> <section> <h2>Section 1.</h2> </section> <section>

    <h3>Section 1.1.</h3> </section> <section>
  34. htmlビルドでの挙動 <div class="section" id="title"> <h1>Title<a class="headerlink" href="#title <div class="section" id="section-1">

    <h2>Section 1.<a class="headerlink" href= <div class="section" id="content-1-1"> <h3>Content 1.1.<a class="headerlink" h </div> <div class="section" id="content-1-2"> <h3>Content 1.2.<a class="headerlink" h </div> </div>
  35. pseudoxmlにする <section ids="title" names="title"> <title> Title <section ids="section-1" names="section\ <title>

    Section 1. <section ids="content-1-1" names="con <title> Content 1.1. <section ids="content-1-2" names="con <title>
  36. どうする? 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('</div>\n')
  37. こうする 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('<section>\n') return if self._proc_first_on_section: self._proc_first_on_section = False self.body.append('</section>\n') self.body.append(f"<section {attrs}>\n") if has child sections(node, 'section'):
  38. 難点 ディレクティブ処理が若干入り組んでいる section ノードを明示的に指定する方法を探せてないため、 section に属性を追加するのが面倒 カスタムディレクティブでしのぎました

  39. まとめ

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

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

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