291 lines
7.8 KiB
Python

from docutils import nodes, utils
from docutils.parsers.rst.roles import set_classes
from docutils.parsers.rst import Directive
from sphinx.util.docutils import SphinxDirective
def setup(app):
app.add_config_value(
'vyos_phabricator_url',
'https://phabricator.vyos.net/', ''
)
app.add_role('vytask', vytask_role)
app.add_role('cfgcmd', cmd_role)
app.add_role('opcmd', cmd_role)
print(app.config.vyos_phabricator_url)
app.add_node(
inlinecmd,
html=(inlinecmd.visit_span, inlinecmd.depart_span),
latex=(inlinecmd.visit_tex, inlinecmd.depart_tex),
text=(inlinecmd.visit_span, inlinecmd.depart_span)
)
app.add_node(
CmdDiv,
html=(CmdDiv.visit_div, CmdDiv.depart_div),
latex=(CmdDiv.visit_tex, CmdDiv.depart_tex),
text=(CmdDiv.visit_div, CmdDiv.depart_div)
)
app.add_node(
CmdBody,
html=(CmdBody.visit_div, CmdBody.depart_div),
latex=(CmdBody.visit_tex, CmdBody.depart_tex),
text=(CmdBody.visit_div, CmdBody.depart_div)
)
app.add_node(
CmdHeader,
html=(CmdHeader.visit_div, CmdHeader.depart_div),
latex=(CmdHeader.tex, CmdHeader.tex),
text=(CmdHeader.visit_div, CmdHeader.depart_div)
)
app.add_node(CfgcmdList)
app.add_directive('cfgcmdlist', CfgcmdlistDirective)
app.add_node(OpcmdList)
app.add_directive('opcmdlist', OpcmdlistDirective)
app.add_directive('cfgcmd', CfgCmdDirective)
app.add_directive('opcmd', OpCmdDirective)
app.connect('doctree-resolved', process_cmd_nodes)
class CfgcmdList(nodes.General, nodes.Element):
pass
class OpcmdList(nodes.General, nodes.Element):
pass
import json
class CmdHeader(nodes.General, nodes.Element):
@staticmethod
def visit_div(self, node):
self.body.append(self.starttag(node, 'div'))
@staticmethod
def depart_div(self, node=None):
# self.body.append('</div>\n')
self.body.append('<a class="cmdlink" href="#%s" ' %
node.children[0]['refid'] +
'title="%s"></a></div>' % (
'Permalink to this Command'))
@staticmethod
def tex(self, node=None):
pass
class CmdDiv(nodes.General, nodes.Element):
@staticmethod
def visit_div(self, node):
self.body.append(self.starttag(node, 'div'))
@staticmethod
def depart_div(self, node=None):
self.body.append('</div>\n')
@staticmethod
def tex(self, node=None):
pass
@staticmethod
def visit_tex(self, node=None):
self.body.append('\n\n\\begin{changemargin}{0cm}{0cm}\n')
@staticmethod
def depart_tex(self, node=None):
self.body.append('\n\\end{changemargin}\n\n')
class CmdBody(nodes.General, nodes.Element):
@staticmethod
def visit_div(self, node):
self.body.append(self.starttag(node, 'div'))
@staticmethod
def depart_div(self, node=None):
self.body.append('</div>\n')
@staticmethod
def visit_tex(self, node=None):
self.body.append('\n\n\\begin{changemargin}{0.5cm}{0.5cm}\n')
@staticmethod
def depart_tex(self, node=None):
self.body.append('\n\\end{changemargin}\n\n')
@staticmethod
def tex(self, node=None):
pass
class inlinecmd(nodes.inline):
@staticmethod
def visit_span(self, node):
self.body.append(self.starttag(node, 'span'))
@staticmethod
def depart_span(self, node=None):
self.body.append('</span>\n')
@staticmethod
def visit_tex(self, node=None):
self.body.append(r'\sphinxbfcode{\sphinxupquote{')
#self.literal_whitespace += 1
@staticmethod
def depart_tex(self, node=None):
self.body.append(r'}}')
#self.literal_whitespace -= 1
class CfgcmdlistDirective(Directive):
def run(self):
return [CfgcmdList('')]
class OpcmdlistDirective(Directive):
def run(self):
return [OpcmdList('')]
class CmdDirective(SphinxDirective):
has_content = True
custom_class = ''
def run(self):
title_list = []
content_list = []
title_text = ''
content_text = ''
has_body = False
cfgmode = self.custom_class + "cmd"
if '' in self.content:
index = self.content.index('')
title_list = self.content[0:index]
content_list = self.content[index + 1:]
title_text = ' '.join(title_list)
content_text = '\n'.join(content_list)
has_body = True
else:
title_text = ' '.join(self.content)
anchor_id = nodes.make_id(self.custom_class + "cmd-" + title_text)
target = nodes.target(ids=[anchor_id])
panel_name = 'cmd-{}'.format(self.custom_class)
panel_element = CmdDiv()
panel_element['classes'] += ['cmd', panel_name]
heading_element = CmdHeader(title_text)
title_nodes, messages = self.state.inline_text(title_text,
self.lineno)
title = inlinecmd(title_text, '', *title_nodes)
target['classes'] += []
title['classes'] += [cfgmode]
heading_element.append(target)
heading_element.append(title)
heading_element['classes'] += [self.custom_class + 'cmd-heading']
panel_element.append(heading_element)
append_list = {
'docname': self.env.docname,
'cmdnode': title.deepcopy(),
'cmd': title_text,
'target': target,
}
if cfgmode == 'opcmd':
if not hasattr(self.env, "vyos_opcmd"):
self.env.vyos_opcmd = []
self.env.vyos_opcmd.append(append_list)
if cfgmode == 'cfgcmd':
if not hasattr(self.env, "vyos_cfgcmd"):
self.env.vyos_cfgcmd = []
self.env.vyos_cfgcmd.append(append_list)
if has_body:
body_element = CmdBody(content_text)
self.state.nested_parse(
content_list,
self.content_offset,
body_element
)
body_element['classes'] += [self.custom_class + 'cmd-body']
panel_element.append(body_element)
return [panel_element]
class OpCmdDirective(CmdDirective):
custom_class = 'op'
class CfgCmdDirective(CmdDirective):
custom_class = 'cfg'
def process_cmd_node(app, cmd, fromdocname):
para = nodes.paragraph()
newnode = nodes.reference('', '')
innernode = cmd['cmdnode']
newnode['refdocname'] = cmd['docname']
newnode['refuri'] = app.builder.get_relative_uri(
fromdocname, cmd['docname'])
newnode['refuri'] += '#' + cmd['target']['refid']
newnode['classes'] += ['cmdlink']
newnode.append(innernode)
para += newnode
return para
def process_cmd_nodes(app, doctree, fromdocname):
env = app.builder.env
for node in doctree.traverse(CfgcmdList):
content = []
for cmd in sorted(env.vyos_cfgcmd, key=lambda i: i['cmd']):
content.append(process_cmd_node(app, cmd, fromdocname))
node.replace_self(content)
for node in doctree.traverse(OpcmdList):
content = []
for cmd in sorted(env.vyos_opcmd, key=lambda i: i['cmd']):
content.append(process_cmd_node(app, cmd, fromdocname))
node.replace_self(content)
def vytask_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
app = inliner.document.settings.env.app
base = app.config.vyos_phabricator_url
ref = base + str(text)
set_classes(options)
node = nodes.reference(
rawtext, utils.unescape(str(text)), refuri=ref, **options)
return [node], []
def cmd_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
node = nodes.literal(text, text)
return [node], []