1717import docutils .utils
1818import setuptools
1919
20- __updated__ = '2020-02-02 '
20+ __updated__ = '2020-02-05 '
2121
2222SETUP_TEMPLATE = '''"""Setup script."""
2323
@@ -139,20 +139,25 @@ def parse_rst(text: str) -> docutils.nodes.document:
139139 return document
140140
141141
142- class SimpleRefCounter (docutils .nodes .NodeVisitor ):
143- """Find all simple references in a given docutils document."""
142+ class RelativeRefFinder (docutils .nodes .NodeVisitor ):
143+ """Find all relative references in a given docutils document that point to existing files ."""
144144
145- def __init__ (self , * args , ** kwargs ):
146- """Initialize the SimpleRefCounter object."""
145+ def __init__ (self , root_dir : pathlib . Path , * args , ** kwargs ):
146+ """Initialize the RelativeRefFinder object."""
147147 super ().__init__ (* args , ** kwargs )
148- self .references = []
148+ self .root_dir = root_dir
149+ self .references : t .List [docutils .nodes .reference ] = []
149150
150151 def visit_reference (self , node : docutils .nodes .reference ) -> None :
151152 """Call for "reference" nodes."""
152153 assert isinstance (node , docutils .nodes .TextElement ), type (node )
153- if len (node .children ) != 1 or not isinstance (node .children [0 ], docutils .nodes .Text ) \
154- or not all (_ in node .attributes for _ in ('name' , 'refuri' )):
154+ # print(f' RelativeRefFinder: examining reference {node}')
155+ # if len(node.children) != 1 or not isinstance(node.children[0], docutils.nodes.Text) \
156+ # or not all(_ in node.attributes for _ in ('name', 'refuri')):
157+ if len (node .children ) != 1 or 'refuri' not in node .attributes \
158+ or any (node .attributes ['refuri' ].startswith (_ ) for _ in {'http://' , 'https://' }):
155159 return
160+ # print(' RelativeRefFinder: reference passed initial check')
156161 path = pathlib .Path (node .attributes ['refuri' ])
157162 try :
158163 if path .is_absolute ():
@@ -161,12 +166,13 @@ def visit_reference(self, node: docutils.nodes.reference) -> None:
161166 except OSError : # in is_absolute() and resolve(), on URLs in Windows
162167 return
163168 try :
164- resolved_path .relative_to (HERE )
169+ resolved_path .relative_to (self . root_dir )
165170 except ValueError :
166171 return
167172 if not path .is_file ():
168173 return
169- assert node .attributes ['name' ] == node .children [0 ].astext ()
174+ # print(' RelativeRefFinder: reference points to existing file')
175+ # assert node.attributes['name'] == node.children[0].astext()
170176 self .references .append (node )
171177
172178 def unknown_visit (self , node : docutils .nodes .Node ) -> None :
@@ -177,19 +183,30 @@ def unknown_visit(self, node: docutils.nodes.Node) -> None:
177183def resolve_relative_rst_links (text : str , base_link : str ) -> str :
178184 """Resolve all relative links in a given string representing an RST document.
179185
186+ Links are resolved only if they point to files existing in the project's working directory.
187+
180188 All links of form `link`_ become `link <base_link/link>`_.
189+
190+ And all
181191 """
182192 document = parse_rst (text )
183- visitor = SimpleRefCounter (document )
184- document .walk (visitor )
185- for target in visitor .references :
186- name = target .attributes ['name' ]
187- uri = target .attributes ['refuri' ]
188- new_link = f'`{ name } <{ base_link } { uri } >`_'
189- if name == uri :
190- text = text .replace (f'`<{ uri } >`_' , new_link )
193+ finder = RelativeRefFinder (HERE , document )
194+ document .walk (finder )
195+ for target in finder .references :
196+ print (f' resolve_relative_rst_links: resolving reference { target } ' )
197+ refuri = target .attributes ['refuri' ]
198+ if 'name' in target .attributes :
199+ name = target .attributes ['name' ]
200+ if name == refuri :
201+ old_link = f'`<{ refuri } >`_'
202+ else :
203+ old_link = f'`{ name } <{ refuri } >`_'
204+ new_link = f'`{ name } <{ base_link } { refuri } >`_'
191205 else :
192- text = text .replace (f'`{ name } <{ uri } >`_' , new_link )
206+ old_link = f' :target: { refuri } '
207+ new_link = f' :target: { base_link } { refuri } '
208+ text = text .replace (old_link , new_link )
209+ print (f' resolve_relative_rst_links: replaced "{ old_link } " with "{ new_link } "' )
193210 return text
194211
195212
0 commit comments