rst2revealjs 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rst2revealjs/__init__.py +0 -0
- rst2revealjs/cli.py +10 -0
- rst2revealjs/engine.py +58 -0
- rst2revealjs/nodes.py +14 -0
- rst2revealjs/py.typed +0 -0
- rst2revealjs/reader.py +39 -0
- rst2revealjs/transforms.py +76 -0
- rst2revealjs/writer.py +98 -0
- rst2revealjs-0.1.0.dist-info/METADATA +73 -0
- rst2revealjs-0.1.0.dist-info/RECORD +12 -0
- rst2revealjs-0.1.0.dist-info/WHEEL +4 -0
- rst2revealjs-0.1.0.dist-info/entry_points.txt +3 -0
rst2revealjs/__init__.py
ADDED
|
File without changes
|
rst2revealjs/cli.py
ADDED
rst2revealjs/engine.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Revealjs.js handler."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import asdict, dataclass
|
|
6
|
+
|
|
7
|
+
from jinja2 import Template
|
|
8
|
+
|
|
9
|
+
DEFAULT_VERSION = "5.2.1"
|
|
10
|
+
|
|
11
|
+
DEFAULT_INIT_SCRIPT = """
|
|
12
|
+
{% for name, url in imports|items -%}
|
|
13
|
+
import {{name}} from "{{url}}";
|
|
14
|
+
{% endfor %}
|
|
15
|
+
|
|
16
|
+
let deck = new Reveal({{arguments}});
|
|
17
|
+
deck.initialize();
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class RevealjsEngine:
|
|
23
|
+
styles: list[str]
|
|
24
|
+
imports: dict[str, str]
|
|
25
|
+
arguments: str = ""
|
|
26
|
+
|
|
27
|
+
def build_stylesheet(self) -> list[str]:
|
|
28
|
+
return [f'<link rel="stylesheet" href="{url}">' for url in self.styles]
|
|
29
|
+
|
|
30
|
+
def build_script(self) -> str:
|
|
31
|
+
tmpl = Template(DEFAULT_INIT_SCRIPT)
|
|
32
|
+
return f"""
|
|
33
|
+
<script type="module">
|
|
34
|
+
{tmpl.render(**asdict(self))}
|
|
35
|
+
</script>
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def from_cdn(
|
|
40
|
+
cls, version: str, theme: str = "black", code_theme: str = "monokai"
|
|
41
|
+
) -> RevealjsEngine:
|
|
42
|
+
styles = [
|
|
43
|
+
f"https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{version}/reveal.min.css",
|
|
44
|
+
f"https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{version}/theme/{theme}.min.css",
|
|
45
|
+
f"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/{code_theme}.min.css",
|
|
46
|
+
]
|
|
47
|
+
imports = {
|
|
48
|
+
"Reveal": f"https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{version}/reveal.esm.min.js",
|
|
49
|
+
"RevealHighlight": f"https://cdnjs.cloudflare.com/ajax/libs/reveal.js/{version}/plugin/highlight/highlight.esm.min.js",
|
|
50
|
+
}
|
|
51
|
+
arguments = """
|
|
52
|
+
{plugins: [RevealHighlight]}
|
|
53
|
+
"""
|
|
54
|
+
return cls(
|
|
55
|
+
styles=styles,
|
|
56
|
+
imports=imports,
|
|
57
|
+
arguments=arguments,
|
|
58
|
+
)
|
rst2revealjs/nodes.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TypedDict
|
|
4
|
+
|
|
5
|
+
from docutils import nodes
|
|
6
|
+
|
|
7
|
+
from .engine import RevealjsEngine
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class revealjs_deck(nodes.General, nodes.Element):
|
|
11
|
+
class Attributes(TypedDict):
|
|
12
|
+
engine: RevealjsEngine
|
|
13
|
+
|
|
14
|
+
attributes: Attributes
|
rst2revealjs/py.typed
ADDED
|
File without changes
|
rst2revealjs/reader.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from docutils.readers.standalone import Reader
|
|
2
|
+
|
|
3
|
+
from . import transforms
|
|
4
|
+
from .engine import DEFAULT_VERSION
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class RevealjsReader(Reader):
|
|
8
|
+
settings_spec = Reader.settings_spec + (
|
|
9
|
+
"Reveal.js Support Options",
|
|
10
|
+
None,
|
|
11
|
+
(
|
|
12
|
+
(
|
|
13
|
+
"Using version of Reveal.js (set latest by default).",
|
|
14
|
+
["--revealjs-version"],
|
|
15
|
+
{"dest": "revealjs_version", "default": DEFAULT_VERSION},
|
|
16
|
+
),
|
|
17
|
+
(
|
|
18
|
+
"Reveal.js theme",
|
|
19
|
+
["--revealjs-theme"],
|
|
20
|
+
{"dest": "revealjs_theme", "default": "black"},
|
|
21
|
+
),
|
|
22
|
+
(
|
|
23
|
+
"Highlight.js theme used in code highlighting.",
|
|
24
|
+
["--highlightjs-theme"],
|
|
25
|
+
{"dest": "highlightjs_theme", "default": "monokai"},
|
|
26
|
+
),
|
|
27
|
+
),
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
def read(self, source, parser, settings):
|
|
31
|
+
settings.doctitle_xform = False # To force setting
|
|
32
|
+
return super().read(source, parser, settings)
|
|
33
|
+
|
|
34
|
+
def get_transforms(self):
|
|
35
|
+
return super().get_transforms() + [
|
|
36
|
+
transforms.RevealjsSectionizeTransform,
|
|
37
|
+
transforms.RevealjsEngineTransform,
|
|
38
|
+
transforms.TitleTransform,
|
|
39
|
+
]
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
from docutils import nodes
|
|
2
|
+
from docutils.transforms import Transform
|
|
3
|
+
|
|
4
|
+
from .engine import RevealjsEngine
|
|
5
|
+
from .nodes import revealjs_deck
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class RevealjsEngineTransform(Transform):
|
|
9
|
+
"""docutils transform to bind Reveal.js engine object."""
|
|
10
|
+
|
|
11
|
+
default_priority = 250
|
|
12
|
+
|
|
13
|
+
def apply(self, **kwargs):
|
|
14
|
+
settings = self.document.settings
|
|
15
|
+
data = {
|
|
16
|
+
"version": settings.revealjs_version,
|
|
17
|
+
"theme": settings.revealjs_theme,
|
|
18
|
+
"code_theme": settings.highlightjs_theme,
|
|
19
|
+
}
|
|
20
|
+
engine = RevealjsEngine.from_cdn(**data)
|
|
21
|
+
node = revealjs_deck(engine=engine)
|
|
22
|
+
self.document.append(node)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RevealjsSectionizeTransform(Transform):
|
|
26
|
+
"""docutils transform to Reveal.js style section structure."""
|
|
27
|
+
|
|
28
|
+
default_priority = 350
|
|
29
|
+
|
|
30
|
+
def apply(self, **kwargs):
|
|
31
|
+
decks = list(self.document.findall(revealjs_deck))
|
|
32
|
+
if not decks or len(decks) > 1:
|
|
33
|
+
raise ValueError("Required only one <revealjs_deck> element to apply it.")
|
|
34
|
+
deck = decks[0]
|
|
35
|
+
deck.parent.remove(deck)
|
|
36
|
+
|
|
37
|
+
def _rebuild(root: nodes.section):
|
|
38
|
+
new_root = nodes.section()
|
|
39
|
+
sub_sections = []
|
|
40
|
+
for child in list(root.findall(nodes.section, include_self=False)):
|
|
41
|
+
if child.parent == root:
|
|
42
|
+
child["revealjs_section_level"] = 3
|
|
43
|
+
root.remove(child)
|
|
44
|
+
sub_sections.append(child)
|
|
45
|
+
new_root.children = [root] + sub_sections
|
|
46
|
+
return new_root
|
|
47
|
+
|
|
48
|
+
idx = self.document.first_child_matching_class(nodes.section)
|
|
49
|
+
if idx is None:
|
|
50
|
+
raise ValueError("Invalid document for revealjs")
|
|
51
|
+
sections = [self.document[idx]]
|
|
52
|
+
sections[0]["revealjs_section_level"] = 1
|
|
53
|
+
for node in self.document.children[:idx]:
|
|
54
|
+
self.document.remove(node)
|
|
55
|
+
sections[0].insert(0, node)
|
|
56
|
+
self.document.remove(sections[0])
|
|
57
|
+
for node in list(sections[0].findall(nodes.section, include_self=False)):
|
|
58
|
+
if node.parent == sections[0]:
|
|
59
|
+
node["revealjs_section_level"] = 2
|
|
60
|
+
sections[0].remove(node)
|
|
61
|
+
sections.append(node)
|
|
62
|
+
for vertical in sections:
|
|
63
|
+
deck.append(_rebuild(vertical))
|
|
64
|
+
|
|
65
|
+
self.document.children = [deck] + self.document.children
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class TitleTransform(Transform):
|
|
69
|
+
default_priority = 351
|
|
70
|
+
|
|
71
|
+
def apply(self, **kwargs):
|
|
72
|
+
for node in self.document.findall(nodes.title):
|
|
73
|
+
self.document["title"] = node.astext()
|
|
74
|
+
break
|
|
75
|
+
else:
|
|
76
|
+
raise ValueError("Title is not found.")
|
rst2revealjs/writer.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Writer for docutils."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from docutils import nodes
|
|
8
|
+
from docutils.writers import html5_polyglot as base_writer
|
|
9
|
+
|
|
10
|
+
from .nodes import revealjs_deck
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class RevealjsTranslator(base_writer.HTMLTranslator):
|
|
14
|
+
"""Custom translator to render body that is Reveal.js presentation.
|
|
15
|
+
|
|
16
|
+
It requires having nested section in doctree.
|
|
17
|
+
We recommend to override settings that ``doctitle_xform`` is ``False``
|
|
18
|
+
when source is simple content.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
documenttag_args = {"tagname": "main", "class": "reveal"}
|
|
22
|
+
|
|
23
|
+
def visit_section(self, node: nodes.section):
|
|
24
|
+
if "revealjs_section_level" in node:
|
|
25
|
+
self.section_level = node["revealjs_section_level"]
|
|
26
|
+
super().visit_section(node)
|
|
27
|
+
|
|
28
|
+
def visit_literal_block(self, node: nodes.Element):
|
|
29
|
+
"""Begin ``literal_block`` .
|
|
30
|
+
|
|
31
|
+
Override base method to open ``pre`` and ``code`` tags simply.
|
|
32
|
+
|
|
33
|
+
:ref: https://github.com/attakei/sphinx-revealjs/blob/master/sphinx_revealjs/writers.py
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def _starttag(tagname: str, suffix: str = "\n", **attributes):
|
|
37
|
+
"""Build start tag to avoide override classes."""
|
|
38
|
+
text = [f"<{tagname}"]
|
|
39
|
+
for key, value in attributes.items():
|
|
40
|
+
if value is None:
|
|
41
|
+
text.append(key.lower())
|
|
42
|
+
else:
|
|
43
|
+
text.append(f'{key}="{value}"')
|
|
44
|
+
text[-1] += f">{suffix}"
|
|
45
|
+
return " ".join(text)
|
|
46
|
+
|
|
47
|
+
# Detect language
|
|
48
|
+
if len(node["classes"]) < 2:
|
|
49
|
+
return super().visit_literal_block(node)
|
|
50
|
+
lang = node["classes"][1]
|
|
51
|
+
# Build <pre> tag
|
|
52
|
+
attrs_pre = {}
|
|
53
|
+
if "data-id" in node:
|
|
54
|
+
attrs_pre["data-id"] = node["data-id"]
|
|
55
|
+
elif isinstance(node.parent, nodes.section) and len(node.parent["ids"]):
|
|
56
|
+
attrs_pre["data-id"] = node.parent["ids"][0]
|
|
57
|
+
self.body.append(_starttag("pre", **attrs_pre))
|
|
58
|
+
# Build <code> tag
|
|
59
|
+
attrs_code = {
|
|
60
|
+
"class": f"language-{lang}",
|
|
61
|
+
"data-trim": None,
|
|
62
|
+
"data-noescape": None,
|
|
63
|
+
}
|
|
64
|
+
if "data-line-numbers" in node:
|
|
65
|
+
attrs_code["data-line-numbers"] = node["data-line-numbers"]
|
|
66
|
+
elif "linenos" in node:
|
|
67
|
+
attrs_code["data-line-numbers"] = "data-line-numbers"
|
|
68
|
+
if "data-ln-start-from" in node:
|
|
69
|
+
attrs_code["data-ln-start-from"] = node["data-ln-start-from"]
|
|
70
|
+
if "data-line-numbers" not in attrs_code:
|
|
71
|
+
attrs_code["data-line-numbers"] = "data-line-numbers"
|
|
72
|
+
self.body.append(_starttag("code", suffix="", **attrs_code))
|
|
73
|
+
# Write code content and close tags.
|
|
74
|
+
self.body.append(node.astext())
|
|
75
|
+
self.body.append("</code></pre>\n")
|
|
76
|
+
# It doesn't walk children, because code content has already been appended.
|
|
77
|
+
raise nodes.SkipNode
|
|
78
|
+
|
|
79
|
+
def visit_revealjs_deck(self, node: revealjs_deck):
|
|
80
|
+
self.body.append(self.starttag(node, "div", CLASS="slides"))
|
|
81
|
+
|
|
82
|
+
def depart_revealjs_deck(self, node: revealjs_deck):
|
|
83
|
+
engine = node.attributes["engine"]
|
|
84
|
+
self.stylesheet = engine.build_stylesheet()
|
|
85
|
+
self.body.append("</div>")
|
|
86
|
+
self.body.append(engine.build_script())
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class RevealjsWriter(base_writer.Writer):
|
|
90
|
+
default_template = Path(__file__).parent / "template.txt"
|
|
91
|
+
|
|
92
|
+
def __init__(self):
|
|
93
|
+
super().__init__()
|
|
94
|
+
self.translator_class = RevealjsTranslator
|
|
95
|
+
|
|
96
|
+
def write(self, document, destination):
|
|
97
|
+
document.settings.initial_header_level = 0 # To force setting
|
|
98
|
+
return super().write(document, destination)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: rst2revealjs
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author: Kazuya Takei
|
|
6
|
+
Author-email: Kazuya Takei <myself@attakei.net>
|
|
7
|
+
Requires-Dist: docutils>=0.21.2
|
|
8
|
+
Requires-Dist: jinja2>=3.1.6
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/x-rst
|
|
11
|
+
|
|
12
|
+
============
|
|
13
|
+
rst2revealjs
|
|
14
|
+
============
|
|
15
|
+
|
|
16
|
+
Simple converter from docutils AST to Reveal.js presentation.
|
|
17
|
+
|
|
18
|
+
Overview
|
|
19
|
+
========
|
|
20
|
+
|
|
21
|
+
This is docutils adapter to write Reveal.js presentation by reStructuredText and other formats.
|
|
22
|
+
You can write presentation by plain text using many expression of reStructuredText.
|
|
23
|
+
|
|
24
|
+
Usage
|
|
25
|
+
=====
|
|
26
|
+
|
|
27
|
+
.. warning:: This section is included plan and it is not availabled yet.
|
|
28
|
+
|
|
29
|
+
.. code:: console
|
|
30
|
+
|
|
31
|
+
pip install rst2revealjs
|
|
32
|
+
|
|
33
|
+
.. code:: rst
|
|
34
|
+
|
|
35
|
+
Title
|
|
36
|
+
=====
|
|
37
|
+
|
|
38
|
+
Section 1
|
|
39
|
+
=========
|
|
40
|
+
|
|
41
|
+
Section 1-1
|
|
42
|
+
-----------
|
|
43
|
+
|
|
44
|
+
.. code:: console
|
|
45
|
+
|
|
46
|
+
rst2revealjs presentation.rst
|
|
47
|
+
|
|
48
|
+
You can see `presentation.html` by your browser.
|
|
49
|
+
|
|
50
|
+
Features
|
|
51
|
+
========
|
|
52
|
+
|
|
53
|
+
This provides some features to realize overview.
|
|
54
|
+
|
|
55
|
+
* Custom directives for specify behaviors about Reveal.js.
|
|
56
|
+
* Writer to generate HTML file using Reveal.js presentation.
|
|
57
|
+
|
|
58
|
+
Motivation
|
|
59
|
+
==========
|
|
60
|
+
|
|
61
|
+
This is re-implement from core features of sphinx-revealjs.
|
|
62
|
+
Because I want to write Reveal.js presentation on Web front-end using Pyodide. [#]_
|
|
63
|
+
|
|
64
|
+
As first goal, I will provide playground website to convert from reStructuredText to presentation using this.
|
|
65
|
+
|
|
66
|
+
License
|
|
67
|
+
=======
|
|
68
|
+
|
|
69
|
+
Apache-2.0 license. Please see LICENSE on repository.
|
|
70
|
+
|
|
71
|
+
.. rubric:: Footnotes
|
|
72
|
+
|
|
73
|
+
.. [#] docutils is registered on Pyodided built-in packages, but Sphinx is not registered.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
rst2revealjs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
rst2revealjs/cli.py,sha256=HChh5TOYmf-B33Sokhv_IOP-uxl9vjUMeSyutyGYjG8,220
|
|
3
|
+
rst2revealjs/engine.py,sha256=LepabBNOedOi2lMxlCTKlfQ8MRUNwhYQ0BY0GDYWcV4,1684
|
|
4
|
+
rst2revealjs/nodes.py,sha256=eMacHzQc5Q6Zl_hWi9V253vd50O-nOpsplDwydFX7xc,274
|
|
5
|
+
rst2revealjs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
rst2revealjs/reader.py,sha256=_0SX-1eoU1CxuTJr1UfbeVN8lfOnJm-odjaDhBAF2S0,1233
|
|
7
|
+
rst2revealjs/transforms.py,sha256=mZpebJvUOj3ZqVAiLcCDFYUdhDhOD1QA_nJcTkc0V5U,2629
|
|
8
|
+
rst2revealjs/writer.py,sha256=VJU9px68afrXfFA8zbrReQtXeD4mL91ASNRHDP7EEbo,3625
|
|
9
|
+
rst2revealjs-0.1.0.dist-info/WHEEL,sha256=eycQt0QpYmJMLKpE3X9iDk8R04v2ZF0x82ogq-zP6bQ,79
|
|
10
|
+
rst2revealjs-0.1.0.dist-info/entry_points.txt,sha256=WDWR2xbO5la36gT_FFYwU9qeL-RuLxX3NNai9vxSdcA,56
|
|
11
|
+
rst2revealjs-0.1.0.dist-info/METADATA,sha256=bzWZYQeeLSeB_gYRa4p1GWVCO8kge_OQJmoH3m-oFs0,1571
|
|
12
|
+
rst2revealjs-0.1.0.dist-info/RECORD,,
|