Last active
September 9, 2022 03:31
-
-
Save osmatsuda/29c37f31ac7f5bbae90b8890baf16e2e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from docutils.core import publish_string | |
from docutils.nodes import TextElement, Inline, Text, unescape | |
from docutils.parsers import rst | |
from docutils.parsers.rst import directives | |
from docutils.writers.html4css1 import Writer, HTMLTranslator | |
import re | |
# ruby node | |
class ruby(Inline, TextElement): pass | |
class rt(Inline, TextElement): pass | |
class rp(Inline, TextElement): pass | |
def build_node(rawtext, node, delimiters='()'): | |
dlm = re.escape(delimiters) | |
rx = re.compile(f"([^{dlm}]+)(\s*[{dlm}]\s*)([^{dlm}]+)(\s*[{dlm}]\s*)") | |
for m in re.finditer(rx, unescape(rawtext)): | |
rbase, rpl, rant, rpr = m.groups() | |
node += [ | |
Text(rbase), | |
rp(rawtext, rpl), | |
rt(rawtext, rant), | |
rp(rawtext, rpr), | |
] | |
return node | |
# ruby directive | |
class Ruby(rst.Directive): | |
required_arguments = 1 | |
option_spec = {'delimiters': directives.unchanged,} | |
def run(self): | |
rawtext = self.arguments[0] | |
node = ruby(rawtext, '', **self.options) | |
return [build_node( | |
rawtext, | |
node, | |
self.options.get('delimiters') | |
)] | |
directives.register_directive('ruby', Ruby) | |
# rubi role | |
def rubi_role(role, rawtext, text, lineno, inliner, options=None, content=None): | |
options = roles.normalized_role_options(options) | |
node = ruby(rawtext, '', **options) | |
return [build_node( | |
rawtext, | |
node, | |
options.get('delimiters') | |
)], [] | |
ruby_role.options = {'delimiters': directives.unchanged} | |
roles.register_canonical_role('rubi', rubi_role) | |
# Transformer and Writer | |
class MyWriter(Writer): | |
def __init__(self): | |
self.parts = {} | |
self.translator_class = MyHTMLTranslator | |
class MyHTMLTranslator(HTMLTranslator): | |
def visit_ruby(self, node): | |
self.body.append(self.starttag(node, 'ruby', suffix='')) | |
def depart_ruby(self, node): | |
self.body.append('</ruby>') | |
def visit_rp(self, node): | |
self.body.append(self.starttag(node, 'rp', suffix='')) | |
def depart_rp(self, node): | |
self.body.append('</rp>') | |
def visit_rt(self, node): | |
self.body.append(self.starttag(node, 'rt', suffix='')) | |
def depart_rt(self, node): | |
self.body.append('</rt>') | |
# Publisher | |
with open(source) as src, \ | |
open(destination, 'wb') as out: | |
output = publish_string(src.read(), writer=MyWriter()) | |
out.write(output) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment