From fbf10cac26085bc907b57fd36ea1dc09b2e6afc1 Mon Sep 17 00:00:00 2001 From: Robert Göhler Date: Sun, 22 Dec 2019 19:31:29 +0100 Subject: Sphinx: create sphinx-vyos extension --- docs/_ext/vyos.py | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 docs/_ext/vyos.py (limited to 'docs') diff --git a/docs/_ext/vyos.py b/docs/_ext/vyos.py new file mode 100644 index 00000000..7ef88d0a --- /dev/null +++ b/docs/_ext/vyos.py @@ -0,0 +1,204 @@ +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) + + print(app.config.vyos_phabricator_url) + + app.add_node( + CmdDiv, + html=(CmdDiv.visit_div, CmdDiv.depart_div), + latex=(CmdDiv.visit_div, CmdDiv.depart_div), + text=(CmdDiv.visit_div, CmdDiv.depart_div) + ) + app.add_node( + CmdHeader, + html=(CmdHeader.visit_div, CmdHeader.depart_div), + latex=(CmdHeader.visit_div, CmdHeader.depart_div), + 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 + + +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('\n') + + +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('\n') + + +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 = nodes.inline(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 = CmdDiv(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], [] -- cgit v1.2.3 From a8a16fbd092e65ce7418037e43ce6da2f140d204 Mon Sep 17 00:00:00 2001 From: Robert Göhler Date: Sun, 22 Dec 2019 19:32:10 +0100 Subject: CSS: custom css for new directives --- docs/_static/css/custom.css | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'docs') diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index a8b94c6e..52bdf6f9 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -1,3 +1,41 @@ +span.opcmd, +span.cfgcmd { + font-weight: bold; + background-color: transparent; + border: none; + padding: 0; + font-size: 100% !important; + max-width: 100%; + color: #000; + font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",Courier,monospace; +} + +.opcmd-heading, +.cfgcmd-heading { + display: block; + margin: 6px 0; + font-size: 90%; + line-height: normal; + background: #e7f2fa; + color: #2980B9; + border-top: solid 3px #6ab0de; + border-top-width: 3px; + border-top-style: solid; + border-top-color: rgb(106, 176, 222); + padding: 6px; +} + +.opcmd-body, +.cfgcmd-body { + margin: 6px 0; + padding-left: 12px; +} + + +a.cmdlink { + font-size: 80%; +} + .wy-nav-content { max-width : none; } -- cgit v1.2.3 From 448e2cb8060845fe1d6e28e74434475a375bd8ea Mon Sep 17 00:00:00 2001 From: Robert Göhler Date: Sun, 22 Dec 2019 19:33:07 +0100 Subject: Sphinx: add extention --- docs/conf.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/conf.py b/docs/conf.py index 76293898..400235e9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,9 +12,9 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) +import os +import sys +sys.path.append(os.path.abspath("./_ext")) # -- Project information ----------------------------------------------------- @@ -41,7 +41,9 @@ release = u'1.3.x (equuleus)' extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.ifconfig', - 'sphinx.ext.graphviz'] + 'sphinx.ext.graphviz', + 'vyos' +] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -170,5 +172,6 @@ texinfo_documents = [ ] def setup(app): - app.add_object_type('opcmd', 'opcmd') - app.add_object_type('cfgcmd', 'cfgcmd') + pass + #app.add_object_type('opcmd', 'opcmd') + #app.add_object_type('cfgcmd', 'cfgcmd') -- cgit v1.2.3 From e983a8dabcf40aa38219dcb7933a137ebcc3f869 Mon Sep 17 00:00:00 2001 From: Robert Göhler Date: Sun, 22 Dec 2019 19:33:51 +0100 Subject: CMDList: add opcmdlist and cfgcmdlist --- docs/appendix/cmd-index.rst | 12 ++++++++++++ docs/index.rst | 1 + 2 files changed, 13 insertions(+) create mode 100644 docs/appendix/cmd-index.rst (limited to 'docs') diff --git a/docs/appendix/cmd-index.rst b/docs/appendix/cmd-index.rst new file mode 100644 index 00000000..28366d02 --- /dev/null +++ b/docs/appendix/cmd-index.rst @@ -0,0 +1,12 @@ +.. cmd-index: + +Operational Command Refercence +============================== + +.. opcmdlist:: + + +Configuration Command Refercence +================================ + +.. cfgcmdlist:: \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 4d25bb09..94b0189a 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -53,6 +53,7 @@ VyOS User Guide appendix/releasenotes appendix/examples/index + appendix/cmd-index appendix/commandtree/index appendix/vyos-on-vmware appendix/vyos-on-baremetal -- cgit v1.2.3 From faf67e43dff6c16aba6df68dbfb490daaa0ff584 Mon Sep 17 00:00:00 2001 From: Robert Göhler Date: Sun, 29 Dec 2019 10:21:10 +0100 Subject: Sphinx: prepare tex layout --- docs/_ext/vyos.py | 56 +++++++++++++++++++++++++++++++++++++++++---- docs/_static/css/custom.css | 18 ++++++++++++++- 2 files changed, 69 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/_ext/vyos.py b/docs/_ext/vyos.py index 7ef88d0a..71b039d1 100644 --- a/docs/_ext/vyos.py +++ b/docs/_ext/vyos.py @@ -11,19 +11,28 @@ def setup(app): '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.tex, inlinecmd.tex), + text=(inlinecmd.visit_span, inlinecmd.depart_span) + ) + app.add_node( CmdDiv, html=(CmdDiv.visit_div, CmdDiv.depart_div), - latex=(CmdDiv.visit_div, CmdDiv.depart_div), + latex=(CmdDiv.tex, CmdDiv.tex), text=(CmdDiv.visit_div, CmdDiv.depart_div) ) app.add_node( CmdHeader, html=(CmdHeader.visit_div, CmdHeader.depart_div), - latex=(CmdHeader.visit_div, CmdHeader.depart_div), + latex=(CmdHeader.tex, CmdHeader.tex), text=(CmdHeader.visit_div, CmdHeader.depart_div) ) app.add_node(CfgcmdList) @@ -44,6 +53,7 @@ class CfgcmdList(nodes.General, nodes.Element): class OpcmdList(nodes.General, nodes.Element): pass +import json class CmdHeader(nodes.General, nodes.Element): @@ -53,7 +63,15 @@ class CmdHeader(nodes.General, nodes.Element): @staticmethod def depart_div(self, node=None): - self.body.append('\n') + # self.body.append('\n') + self.body.append('' % ( + 'Permalink to this Command')) + + @staticmethod + def tex(self, node=None): + pass class CmdDiv(nodes.General, nodes.Element): @@ -66,6 +84,31 @@ class CmdDiv(nodes.General, nodes.Element): def depart_div(self, node=None): self.body.append('\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('\n') + + @staticmethod + def tex(self, node=None): + print('=====================') + #print(json.dumps(dir(self))) + print('---------------------') + print((self.visit_inline)) + exit() + #self.body.append('\\chapter') + pass + class CfgcmdlistDirective(Directive): @@ -114,7 +157,7 @@ class CmdDirective(SphinxDirective): title_nodes, messages = self.state.inline_text(title_text, self.lineno) - title = nodes.inline(title_text, '', *title_nodes) + title = inlinecmd(title_text, '', *title_nodes) target['classes'] += [] title['classes'] += [cfgmode] heading_element.append(target) @@ -202,3 +245,8 @@ def vytask_role(name, rawtext, text, lineno, inliner, options={}, content=[]): 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], [] diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 52bdf6f9..a1e34259 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -12,7 +12,7 @@ span.cfgcmd { .opcmd-heading, .cfgcmd-heading { - display: block; + display: inline-block; margin: 6px 0; font-size: 90%; line-height: normal; @@ -32,8 +32,24 @@ span.cfgcmd { } + +.cfgcmd-heading .cmdlink:after, +.opcmd-heading .cmdlink:after { + content: ""; + font-family: FontAwesome +} + + +.cfgcmd-heading:not(:hover) .cmdlink, +.opcmd-heading:not(:hover) .cmdlink { + display: none; +} + + + a.cmdlink { font-size: 80%; + margin-left: 6px; } .wy-nav-content { -- cgit v1.2.3 From fa0a2ec10cea60b438b67b8b7a7143cdcbb082b8 Mon Sep 17 00:00:00 2001 From: Robert Göhler Date: Sat, 4 Jan 2020 12:42:18 +0100 Subject: latex: add preamble for directive block --- docs/conf.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'docs') diff --git a/docs/conf.py b/docs/conf.py index 400235e9..b5e67368 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -136,6 +136,9 @@ latex_elements = { # Latex figure (float) alignment # # 'figure_align': 'htbp', + 'preamble': r'''\def\changemargin#1#2{\list{}{\rightmargin#2\leftmargin#1}\item[]} +\let\endchangemargin=\endlist''', + } # Grouping the document tree into LaTeX files. List of tuples -- cgit v1.2.3 From d2159df64738df01474b248f572c23b735d9ed0e Mon Sep 17 00:00:00 2001 From: Robert Göhler Date: Sat, 4 Jan 2020 12:48:07 +0100 Subject: sphinx: implement latex layout --- docs/_ext/vyos.py | 60 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 11 deletions(-) (limited to 'docs') diff --git a/docs/_ext/vyos.py b/docs/_ext/vyos.py index 71b039d1..7a3d75ba 100644 --- a/docs/_ext/vyos.py +++ b/docs/_ext/vyos.py @@ -19,16 +19,22 @@ def setup(app): app.add_node( inlinecmd, html=(inlinecmd.visit_span, inlinecmd.depart_span), - latex=(inlinecmd.tex, inlinecmd.tex), + 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.tex, CmdDiv.tex), + 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), @@ -88,6 +94,38 @@ class CmdDiv(nodes.General, nodes.Element): 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('\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): @@ -100,14 +138,14 @@ class inlinecmd(nodes.inline): self.body.append('\n') @staticmethod - def tex(self, node=None): - print('=====================') - #print(json.dumps(dir(self))) - print('---------------------') - print((self.visit_inline)) - exit() - #self.body.append('\\chapter') - pass + 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): @@ -185,7 +223,7 @@ class CmdDirective(SphinxDirective): self.env.vyos_cfgcmd.append(append_list) if has_body: - body_element = CmdDiv(content_text) + body_element = CmdBody(content_text) self.state.nested_parse( content_list, self.content_offset, -- cgit v1.2.3 From 5b3160976a84eb019b1107dbbcb17cd746eeec40 Mon Sep 17 00:00:00 2001 From: Robert Göhler Date: Sat, 4 Jan 2020 12:56:19 +0100 Subject: conf.py: resolve merge conflict --- docs/conf.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'docs') diff --git a/docs/conf.py b/docs/conf.py index b5e67368..09b7a958 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -176,5 +176,3 @@ texinfo_documents = [ def setup(app): pass - #app.add_object_type('opcmd', 'opcmd') - #app.add_object_type('cfgcmd', 'cfgcmd') -- cgit v1.2.3 From 156eef177980052027db572e4b60d984626e0081 Mon Sep 17 00:00:00 2001 From: Robert Göhler Date: Sat, 4 Jan 2020 14:09:08 +0100 Subject: Documentation: add :cfgcmd: and :opcmd: inline commands --- docs/contributing/documentation.rst | 71 +++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 14 deletions(-) (limited to 'docs') diff --git a/docs/contributing/documentation.rst b/docs/contributing/documentation.rst index 48cc063b..29b33cdd 100644 --- a/docs/contributing/documentation.rst +++ b/docs/contributing/documentation.rst @@ -5,12 +5,12 @@ Documentation As most software projects we also have a lack in documentation. We encourage every VyOS user to help us improve our documentation. This will not only be -benefical four you (when reading something up) but also for the whole world. +beneficial for you (when reading something up) but also for the whole world. -If you are willing to contribute to our documentation this is the definate -guid how to do so. +If you are willing to contribute to our documentation this is the definite +guide how to do so. -.. note:: In contrast to submitting code patches there is no requirement that +.. note:: In contrast to submitting code patches, there is no requirement that you open up a Phabricator_ task prior to submitting a Pull-Request to the documentation. @@ -147,29 +147,72 @@ system numbers for the documentation: Please don't use other public address space. - Custom Sphinx-doc Markup ^^^^^^^^^^^^^^^^^^^^^^^^ -When documenting CLI commands use the ``.. cfgcmd::`` directive for all -configuration mode commands. When documenting operational level command use -the ``.. opcmd::`` directive. An explanation of the described command should -be added below this statement. +When writing the documentation custom commands have been developed. Please +make yourself comfortable with those commands as this eases the way we +render the documentation. -**Example** +cfgcmd +"""""" -.. code-block:: none +When documenting CLI commands use the ``.. cfgcmd::`` directive for all +configuration mode commands. An explanation of the described command should be +added below this statement. - .. opcmd:: show protocols static arp +With those custom commands it will be possible to render them in a more +descriptive way in the resulting HTML/PDF manual. - Display all known ARP table entries spanning accross all interfaces +.. code-block:: none .. cfgcmd:: set protocols static arp 192.0.2.100 hwaddr 00:53:27:de:23:aa This will configure a static ARP entry always resolving `192.0.2.100` to `00:53:27:de:23:aa`. +For a inline configuration level command use ``:cfgcmd:`` + +.. code-block:: none + + :cfgcmd:`set interface ethernet eth0` + +opcmd +""""" + +When documenting operational level command use the ``.. opcmd::`` directive. +An explanation of the described command should be added below this statement. + +With those custom commands it will be possible to render them in a more +descriptive way in the resulting HTML/PDF manual. + +.. code-block:: none + + .. opcmd:: show protocols static arp + + Display all known ARP table entries spanning across all interfaces + +For a inline operational level command use ``:opcmd:`` + +.. code-block:: none + + :opcmd:`add system image` + +vytask +"""""" + +When referencing to VyOS Phabricator Tasks, there is a custom Sphinx Markup +command called ``vytask`` which automatically renders to a proper Phabricator +URL. This is heavily used in the :ref:`release-notes` section. + +.. code-block:: none + + * :vytask:`T1605` Fixed regression in L2TP/IPsec server + * :vytask:`T1613` Netflow/sFlow captures IPv6 traffic correctly + + .. _Sphinx-doc: https://www.sphinx-doc.org .. _reStructuredText: http://www.sphinx-doc.org/en/master/usage/restructuredtext/index.html -.. _Phabricator: https://phabricator.vyos.net .. _README.md: https://github.com/vyos/vyos-documentation/blob/master/README.md + +.. include:: ../common-references.rst \ No newline at end of file -- cgit v1.2.3 From 1d7328e3b701b12a4613c9dc91f4688220b577b2 Mon Sep 17 00:00:00 2001 From: Robert Göhler Date: Sat, 4 Jan 2020 14:21:49 +0100 Subject: BGP: fix ref error --- docs/routing/bgp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/routing/bgp.rst b/docs/routing/bgp.rst index 14ea1238..41be5c6c 100644 --- a/docs/routing/bgp.rst +++ b/docs/routing/bgp.rst @@ -76,7 +76,7 @@ bottom until one of the factors can be used. 6. **MED check** Where routes with a MED were received from the same AS, prefer the route - with the lowest MED. :ref:`bgp-med`. + with the lowest MED. 7. **External check** -- cgit v1.2.3