#
# The documentation generation process is tightly integrated with the
# scons build framework:
-#
+#
# * SCons analyzes the Doxyfile's to find all the documentation
# dependencies. This happens in the doxygen builder in
# senfscons/Doxygen.py.
#
# * the doclib/doxy-header.html and/or doclib/doxy-footer.html files
# are regenerated
-#
+#
# * If any documentation is out-of-date with respect to it's source
# files, the documentation is regenerated.
-#
+#
# * To fix some link errors, the additional 'linklint' and 'fixlinks'
# targets are used
#
-#
+#
# 1. Scanning the Doxyfile's
-#
+#
# The doxygen builder scans all documentation source files which have
# the text 'doxyfile' in any case in their name. It understands
# @INCLUDE directives and will find all the dependencies of the
# documentation:
-#
+#
# * All the source files as selected by INPUT, INPUT_PATTERN,
# RECURSIVE and so on.
-#
+#
# * Any referenced tag-files
-#
+#
# * Documentation header and/or footer
-#
+#
# * The INPUT_FILTER program
-#
+#
# * Any included doxygen configuration files
-#
+#
#
# 2. Regenerating header and/or footer
#
# using a simple python based templating system called yaptu which is
# included in site_scons/lib/.
#
-#
+#
# 3. Calling doxygen
-#
+#
# The doxygen call itself is quite complex since there is some pre-
# and post-processing going on. We can separate this step into two
# steps
# 3.2. The main doxygen build (Doxygen builder)
#
# The Doxygen builder will call the doxygen command to build the
-# documentation.
+# documentation.
#
# The doxygen command is configured as 'site_scon/lib/doxygen.sh' which
# does some additional processing in addition to calling doxygen
# * it sets environment variables depending on command line arguments.
# These variables are then used in the Doxyfile's
#
-# * after doxygen is finished, 'installdox' is called to resolve
+# * after doxygen is finished, 'installdox' is called to resolve
# tag file references.
#
# * the HTML documentation is post-processed using some sed, tidy, and
pathbase = env.Dir('#/senf').abspath
pathbasel = len(pathbase)+1
for module in env.Alias('all_docs')[0].sources:
- if module.name != 'html.stamp' : continue
+ if module.name != 'html.stamp' : continue
if not module.dir.dir.dir.abspath.startswith(pathbase): continue
mods[module.dir.dir.dir.abspath] = [ module.dir.dir.dir.abspath[pathbasel:].replace('/','_'),
module.dir.dir.dir.name,
module.dir.abspath[pathbasel:],
0 ]
-
+
rv = []
keys = mods.keys()
keys.sort()
<div id="title2">
<div id="search">
<form action="@TOPDIR@/doclib/search.php" method="get">
- Search: <input type="text" name="query" size="20" accesskey="s"/>
+ Search: <input type="text" name="query" size="20" accesskey="s"/>
</form>
</div>
<h1>SENF Extensible Network Framework</h1>
env.PhonyTarget('linklint', [], [
'rm -rf doc/linklint',
'linklint -doc doc/linklint -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
- '[ ! -r doc/linklint/errorX.html ] || python doclib/linklint_addnames.py <doc/linklint/errorX.html >doc/linklint/errorX.html.new',
- '[ ! -r doc/linklint/errorX.html.new ] || mv doc/linklint/errorX.html.new doc/linklint/errorX.html',
- '[ ! -r doc/linklint/errorAX.html ] || python doclib/linklint_addnames.py <doc/linklint/errorAX.html >doc/linklint/errorAX.html.new',
- '[ ! -r doc/linklint/errorAX.html.new ] || mv doc/linklint/errorAX.html.new doc/linklint/errorAX.html',
])
env.PhonyTarget('fixlinks', [], [
- 'python doclib/fix-links.py -v -s .svn -s linklint -s debian doc/linklint/errorX.txt doc/linklint/errorAX.txt',
+ 'python doclib/fix-links.py -v -s .svn -s linklint -s debian -s doclib -s search',
])
header = env.Command('doxy-header.html', 'SConscript', writeTemplate,
s = s.replace(" "," ").replace("\n"," ")
s = REF_RE.sub("?",s)
return s.strip()
-
+
class LinkFixer:
def __init__(self, skipdirs=('.svn',)):
def init(self):
self._index.build()
- self._files = 0
- self._found = 0
- self._fixed = 0
- self._removed = {}
class LinkFilter(HTMLFilter):
- def __init__(self, index, key, topdir, out):
+ def __init__(self, index, topdir, out):
HTMLFilter.__init__(self, out)
self._index = index
- self._key = key
self._topdir = topdir
- self._found = 0
- self._fixed = 0
- self._removed = {}
- def _s_A(self, attrs):
- self._skip_a = False
- if self._key in dict(attrs).get('href',''):
- self._found += 1
- ix = [ i for i, attr in enumerate(attrs) if attr[0] == 'href' ][0]
- anchor = attrs[ix][1]
- if '#' in anchor:
- anchor = anchor.split('#')[1]
- a = anchor
- target = None
- while not target:
- target = self._index[a]
- if target:
- target = '%s#%s' % (target, a)
- elif a.startswith('g'):
- a = a[1:]
- else:
- break
- else:
- anchor = os.path.split(anchor)[1]
- target = self._index[anchor]
+ def _check(self, tag, linkAttr, attrs):
+ ix = target = None
+ for i,(k,v) in enumerate(attrs):
+ if k == linkAttr:
+ ix, target = i, v
+ break
+ if target:
+ fix = False
+ tdir = anchor = None
+ if '#' in target : target, anchor = target.rsplit('#',1)
+ if '/' in target : tdir, target = target.rsplit('/', 1)
+ newTarget = None
+ if anchor:
+ newTarget = self.anchorLookup(anchor)
+ if newTarget is None:
+ newTarget = self.fileLookup(target)
+ if newTarget:
+ attrs[ix] = (attrs[ix][0], '/'.join((self._topdir, newTarget)))
+ self.emit_starttag(tag, attrs)
+
+ def anchorLookup(self,anchor):
+ target = None
+ while not target:
+ target = self._index[anchor]
if target:
- self._fixed += 1
- attrs[ix] = ('href', os.path.join(self._topdir,target))
+ target = '%s#%s' % (target, anchor)
+ elif anchor.startswith('g'):
+ anchor = anchor[1:]
else:
- self._removed[anchor] = {}
- self._collectFor = anchor
- self.startCollect()
- return
- self.emit_starttag('a',attrs)
-
- def _e_A(self):
- if self.collecting():
- self._removed[self._collectFor][stripHTML(self.endCollect())] = None
- else:
- self.emit_endtag('a')
-
- def stats(self):
- return (self._found, self._fixed, self._removed)
-
- def fix(self, path, target):
- self._files += 1
+ break
+ return target
+
+ def fileLookup(self,target):
+ return self._index[target]
+
+ def _s_A(self, attrs):
+ self._check('a', 'href', attrs)
+
+ def _s_AREA(self, attrs):
+ self._check('area', 'href', attrs)
+
+ def fix(self, path):
data = codecs.open(path, "r", "utf-8").read()
filt = LinkFixer.LinkFilter(self._index,
- target,
- "../" * (len(os.path.split(path)[0].split("/"))),
+ ("../" * (len(os.path.split(path)[0].split("/"))))[:-1],
codecs.open(path, "w", "utf-8") )
filt.feed(data)
filt.close()
- found, fixed, removed = filt.stats()
- self._found += found
- self._fixed += fixed
- for anchor, labels in removed.items():
- for label in labels.keys():
- self._removed.setdefault((anchor,label),{})[path] = None
-
- def stats(self):
- return (self._files, self._found, self._fixed, self._removed)
-
+
(opts, args) = getopt.getopt(sys.argv[1:], "vs:")
-if len(args) != 2:
- sys.stderr.write("""Usage: fix-links.py [-s skip-dir]... <errrorX.txt> <errorAX.txt>
+if len(args) != 0:
+ sys.stderr.write("""Usage: fix-links.py [-s skip-dir]...
-Process the 'errorX.txt' and 'errorAX.txt' files as generated by
-'linklint': Check all invalid links and try to find the correct
-target. If a target is found, the link is changed accordingly,
-otherwise the link is removed.
+Check all links and try to find the correct target. If a target is
+found, the link is changed accordingly, otherwise the link is removed.
To find anchors, fix-links.py generates a complete index of all
anchors defined in any HTML file in the current directory or some
skipdirs = [ val for opt, val in opts if opt == '-s' ]
verbose = ( '-v', '' ) in opts
-if not os.path.exists(args[0]) and not os.path.exists(args[1]):
- # No bad links to nothing to do
- sys.exit(0)
-
fixer = LinkFixer(skipdirs)
fixer.init()
-target = None
-
-if os.path.exists(args[0]):
- for l in file(args[0]):
- l = l.rstrip()
- if l.startswith('/'):
- target = '#' + os.path.split(l)[1]
- elif l.startswith(' /') and not l.endswith('/'):
- sys.stderr.write("%s\n" % l)
- fixer.fix(l[5:], target)
-
-if os.path.exists(args[1]):
- for l in file(args[1]):
- l = l.rstrip()
- if l.startswith('/'):
- target = l.split('#')[1]
- elif l.startswith(' /') and not l.endswith('/'):
- sys.stderr.write("%s\n" % l)
- fixer.fix(l[5:], target)
-
-total, found, fixed, removed = fixer.stats()
-
-if verbose:
- sys.stderr.write("\nRemoved links:\n")
- for (anchor, label), files in removed.items():
- sys.stderr.write("%-36.36s %-48.48s %s\n"
- % ( anchor,
- "(%s)" % label[:46],
- " ".join(files.keys())) )
-
-sys.stderr.write("""
-Files processed : %5d
-Links processed : %5d
-Links fixed : %5d
-Links removed : %5d
-""" % (total, found, fixed, found-fixed))
+for dirname, subdirs, files in os.walk('.'):
+ for d in skipdirs:
+ if d in subdirs:
+ subdirs.remove(d)
+ for f in fnmatch.filter(files,'*.html'):
+ path = os.path.normpath(os.path.join(dirname, f))
+ print path
+ fixer.fix(path)
+++ /dev/null
-#!/usr/bin/python
-
-import HTMLParser, re, sys, os.path
-
-class ScanLinks(HTMLParser.HTMLParser):
-
- def __init__(self, target, base):
- HTMLParser.HTMLParser.__init__(self)
- self._target = target
- self._base = base
- self._collect = False
- self._data = ""
- self._value = ""
-
- def startCollect(self):
- self._collect = True
- self._data = ""
-
- def endCollect(self):
- self._collect = False
- return self._data
-
- def collecting(self):
- return self._collect
-
- def handle_starttag(self,tag,attrs):
- m = getattr(self,'_s_'+tag.upper(),None)
- if m:
- m(attrs)
-
- def handle_endtag(self,tag):
- m = getattr(self,'_e_'+tag.upper(),None)
- if m:
- m()
-
- def handle_data(self,data):
- if self._collect:
- self._data += data
-
- def handle_charref(self,name):
- self.handle_data(name)
-
- def handle_entityref(self,name):
- self.handle_data(name)
-
- def value(self):
- return self._value
-
- ###########################################################################
-
- SCHEME_RE=re.compile("[a-z]+:")
-
- def _s_A(self,attrs):
- attrs = dict(attrs)
- url = attrs.get('href')
- if url and not self.SCHEME_RE.match(url):
- if '#' in self._target:
- p = os.path.abspath(os.path.join(self._base,url))
- else:
- p = os.path.abspath(os.path.join(self._base,url.split('#')[0]))
- if p == self._target:
- self.startCollect()
-
- def _e_A(self):
- if self.collecting():
- self._value = self.endCollect()
-
-WS_RE=re.compile("\\s+")
-
-def linkName(target,f):
- scanner = ScanLinks(target,os.path.split(os.path.abspath(f))[0])
- scanner.feed(file(f).read())
- return WS_RE.sub(' ',scanner.value().strip())
-
-process = 0
-target = 0
-for line in sys.stdin:
- if line.startswith('<a href='):
- target = line.split(':')[1]
- target = target[2:].split('"')[0]
- elif line.startswith(' <a href='):
- f = line.split(':')[1]
- f = f[2:].split('"')[0]
- line = '%s (%s)</a>\n' % (line[:-5], linkName(target,f))
- sys.stdout.write(line)