diff --git a/README.rst b/README.rst index d8de5b8..97ccd17 100644 --- a/README.rst +++ b/README.rst @@ -1,3 +1,4 @@ +================== jandd.sphinxext.ip ================== @@ -5,10 +6,30 @@ This is an IP address extension for `Sphinx`_. The extension provides a domain *ip* that allows marking IPv4 and IPv6 addresses in documentation and contains directives to collect information regarding IP addresses in IP ranges. +.. _Sphinx: http://www.sphinx-doc.org/ + +Development +=========== + +The extension is developed in a git repository that can be cloned by running:: + + git clone https://git.dittberner.info/sphinxext-ip.git + +A repository browser is available at +https://git.dittberner.info/?p=sphinxext-ip.git. + Contributors ------------- +============ * `Jan Dittberner`_ .. _Jan Dittberner: https://jan.dittberner.info/ -.. _Sphinx: http://www.sphinx-doc.org/ + +Changes +======= + +0.2.0 - 2016-05-04 +------------------ + +* display IP address lists as tables +* sort IP address lists numericaly diff --git a/jandd/sphinxext/ip.py b/jandd/sphinxext/ip.py index 8f03776..0c71bda 100644 --- a/jandd/sphinxext/ip.py +++ b/jandd/sphinxext/ip.py @@ -8,7 +8,6 @@ :copyright: Copyright (c) 2016 Jan Dittberner :license: GPLv3+, see COPYING file for details. """ -__version__ = '0.1.1' import re @@ -24,15 +23,20 @@ from sphinx.locale import l_ from sphinx.roles import XRefRole from sphinx.util.nodes import make_refnode +__version__ = '0.2.0' + def ip_object_anchor(typ, path): path = re.sub(r'[.:/]', '-', path) return typ.lower() + '-' + path -class ip_node(nodes.Inline, nodes.TextElement): pass +class ip_node(nodes.Inline, nodes.TextElement): + pass -class ip_range(nodes.General, nodes.Element): pass + +class ip_range(nodes.General, nodes.Element): + pass class IPXRefRole(XRefRole): @@ -42,7 +46,7 @@ class IPXRefRole(XRefRole): def __init__(self, method, index_type, **kwargs): self.method = method self.index_type = index_type - innernodeclass=None + innernodeclass = None if method in ('v4', 'v6'): innernodeclass = ip_node super(IPXRefRole, self).__init__( @@ -230,36 +234,85 @@ def process_ips(app, doctree): node.replace_self(replacement) -def sort_ip_info(item): - return item['ip'] +def sort_ip(item): + return Network(item).ip + + +def create_table_row(rowdata): + row = nodes.row() + for cell in rowdata: + entry = nodes.entry() + row += entry + entry += cell + return row def process_ip_nodes(app, doctree, fromdocname): env = app.builder.env domaindata = env.domaindata[IPDomain.name] + header = (l_('IP address'), l_('Used by')) + colwidths = (1, 3) + for node in doctree.traverse(ip_range): content = [] net = Network(node['rangespec']) - for ip_info in sorted(domaindata['ips'], key=sort_ip_info): - if ip_info['ip'] in net: + ips = {} + for key, value in [ + (ip_info['ip'], ip_info) for ip_info in + domaindata['ips'] if ip_info['ip'] in net + ]: + addrlist = ips.get(key, []) + addrlist.append(value) + ips[key] = addrlist + if ips: + table = nodes.table() + tgroup = nodes.tgroup(cols=len(header)) + table += tgroup + for colwidth in colwidths: + tgroup += nodes.colspec(colwidth=colwidth) + thead = nodes.thead() + tgroup += thead + thead += create_table_row([ + nodes.paragraph(text=label) for label in header]) + tbody = nodes.tbody() + tgroup += tbody + for ip, ip_info in [ + (ip, ips[ip]) for ip in sorted(ips, key=sort_ip) + ]: para = nodes.paragraph() - para += nodes.literal('', ip_info['ip']) - ids = ip_object_anchor(ip_info['typ'], ip_info['ip']) - para['ids'].append(ids) - domaindata[ip_info['typ']][ids] = (fromdocname, '') - newnode = nodes.reference('', '', internal=True) - try: - newnode['refuri'] = app.builder.get_relative_uri( - fromdocname, ip_info['docname']) - except NoUri: - pass - title = env.titles[ip_info['docname']] - innernode = nodes.Text(title.astext()) - newnode.append(innernode) - para += nodes.Text(" in ") - para += newnode - content.append(para) + para += nodes.literal('', ip) + refnode = nodes.paragraph() + refuris = set() + refnodes = [] + for item in ip_info: + ids = ip_object_anchor(item['typ'], item['ip']) + if ids not in para['ids']: + para['ids'].append(ids) + + domaindata[item['typ']][ids] = (fromdocname, '') + newnode = nodes.reference('', '', internal=True) + try: + newnode['refuri'] = app.builder.get_relative_uri( + fromdocname, item['docname']) + if newnode['refuri'] in refuris: + continue + refuris.add(newnode['refuri']) + except NoUri: + pass + title = env.titles[item['docname']] + innernode = nodes.Text(title.astext()) + newnode.append(innernode) + refnodes.append(newnode) + for count in range(len(refnodes)): + refnode.append(refnodes[count]) + if count < len(refnodes) - 1: + refnode.append(nodes.Text(", ")) + tbody += create_table_row([para, refnode]) + content.append(table) + else: + para = nodes.paragraph(l_('No IP addresses in this range')) + content.append(para) node.replace_self(content) diff --git a/setup.py b/setup.py index db7357b..b992734 100644 --- a/setup.py +++ b/setup.py @@ -2,14 +2,11 @@ from setuptools import setup, find_packages -version = '0.1.1' +version = '0.2.0' with open('README.rst') as readme: description = readme.read() + "\n\n" -with open('COPYING') as license: - description += license.read() - requires = ['Sphinx>=1.4', 'ipcalc>=1.99'] tests_requires = ['path.py>=8.2.1'] @@ -17,12 +14,13 @@ tests_requires = ['path.py>=8.2.1'] setup( author="Jan Dittberner", author_email="jan@dittberner.info", - description="IP address extensions for Sphinx", + description="IP address extension for Sphinx", long_description=description, include_package_data=True, install_requires=requires, keywords="sphinx extension IP", license="GPLv3+", + url="https://pypi.python.org/pypi/jandd.sphinxext.ip", name="jandd.sphinxext.ip", namespace_packages=['jandd', 'jandd.sphinxext'], packages=find_packages(), diff --git a/tests/root/index.rst b/tests/root/index.rst index 8ada3e1..4b2e15e 100644 --- a/tests/root/index.rst +++ b/tests/root/index.rst @@ -13,6 +13,7 @@ Contents: testpage1 testpage2 + testpage3 Indices and tables diff --git a/tests/root/testpage3.rst b/tests/root/testpage3.rst new file mode 100644 index 0000000..ae38493 --- /dev/null +++ b/tests/root/testpage3.rst @@ -0,0 +1,4 @@ +Test page 3 +=========== + +This page contains :ip:v6:`2001:dead:beef::1` like :doc:`testpage2` does.