Skip to content

Commit fa60cef

Browse files
committed
cleaning up
1 parent 630b3c1 commit fa60cef

File tree

3 files changed

+104
-75
lines changed

3 files changed

+104
-75
lines changed

linkcheck.py

Lines changed: 78 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,20 @@
2626

2727
# For more information, please refer to <http://unlicense.org>
2828

29-
"""Check for broken links."""
29+
"""Check for broken links.
30+
31+
This finds links like this...
32+
33+
[click here](some-file.md)
34+
[or here](../some/path/another-file.md)
35+
![here's an image](../images/some-cool-image.png)
36+
37+
...but not like this:
38+
39+
[some website](http://github.com/)
40+
[another website](https://github.com/)
41+
[local header](#some-header)
42+
"""
3043

3144
# The markdown files use posix-style paths, so we need posixpath for
3245
# processing them. See help('posixpath').
@@ -38,32 +51,61 @@
3851
import common
3952

4053

41-
Link = collections.namedtuple('Link', 'text target markdown lineno file')
54+
class Link:
4255

56+
def __init__(self, regexmatch, filepath, lineno):
57+
# The .group(0) is not perfect, but it's good enough.
58+
self.markdown = regexmatch.group(0)
59+
self.text = regexmatch.group(1)
60+
self.target = regexmatch.group(2)
61+
self.filepath = filepath
62+
self.lineno = lineno
63+
self.status = None
4364

44-
def check_link(link):
45-
"""Check if the link's target exists.
46-
47-
Return an error message string or "ok".
48-
"""
49-
if link.target.startswith(('http://', 'https://')):
50-
# Checking for http(s) links can be added later, but currently
51-
# it's not needed.
52-
return "ok"
53-
path = posixpath.join(posixpath.dirname(link.file), link.target)
54-
realpath = path.replace('/', os.sep)
55-
if not os.path.exists(realpath):
56-
return "doesn't exist"
57-
if path.endswith('/'):
58-
# A directory.
59-
if os.path.isdir(realpath):
60-
return "ok"
61-
return "not a directory"
62-
else:
63-
# A file.
64-
if os.path.isfile(realpath):
65+
def _get_status(self):
66+
if self.target.startswith(('http://', 'https://')):
67+
# Checking for http(s) links can be added later, but
68+
# currently it's not needed.
6569
return "ok"
66-
return "not a file"
70+
71+
target = self.target
72+
if '#' in target:
73+
where = target.index('#')
74+
if where == 0:
75+
# It's a link to a title in the same file, we need to
76+
# skip it.
77+
return "ok"
78+
target = target[:where]
79+
80+
path = posixpath.join(posixpath.dirname(self.filepath), target)
81+
realpath = path.replace('/', os.sep)
82+
83+
if not os.path.exists(realpath):
84+
return "doesn't exist"
85+
if target.endswith('/'):
86+
# A directory.
87+
if os.path.isdir(directory):
88+
return "ok"
89+
return "not a directory"
90+
else:
91+
# A file.
92+
if os.path.isfile(realpath):
93+
return "ok"
94+
return "not a file"
95+
96+
def check(self):
97+
"""Check if the link's target is like it should be.
98+
99+
Return an error message string or "ok". The return value is also
100+
assigned to the status attribute.
101+
"""
102+
self.status = self._get_status()
103+
return self.status
104+
105+
def print_status(self):
106+
print(" file {0.filepath}, line {0.lineno}: {0.status}".format(self))
107+
print(" " + self.markdown)
108+
print()
67109

68110

69111
def main():
@@ -72,35 +114,22 @@ def main():
72114
for path in common.get_markdown_files():
73115
with open(path.replace('/', os.sep), 'r') as f:
74116
for match, lineno in common.find_links(f):
75-
target = match.group(2)
76-
if '#' in target:
77-
where = target.index('#')
78-
target = target[:where]
79-
link = Link(
80-
text=match.group(1),
81-
target=target,
82-
markdown=match.group(0),
83-
lineno=lineno,
84-
file=path)
85-
links.append(link)
117+
links.append(Link(match, path, lineno))
118+
print(" found", len(links), "links")
86119

87120
print("Checking for broken links...")
88-
broken = [] # [(Link, check result), ...]
121+
brokens = 0
89122
for link in links:
90-
result = check_link(link)
91-
if result != "ok":
92-
broken.append((link, result))
93-
94-
if broken:
95-
print("\n*** %d/%d links seem to be broken! ***\n"
96-
% (len(broken), len(links)))
97-
for link, error in broken:
98-
print(" file {0.file}, line {0.lineno}: {1}"
99-
.format(link, error))
100-
print(" ", link.markdown.replace('\n', ' '))
101-
print()
123+
if link.check() != "ok":
124+
link.print_status()
125+
brokens += 1
126+
127+
if brokens == 0:
128+
print("All links seem to be OK.")
129+
elif brokens == 1:
130+
print("1 link is broken!")
102131
else:
103-
print("All", len(links), "links seem to be OK.")
132+
print(brokens, "links are broken!")
104133

105134

106135
if __name__ == '__main__':

strip.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ def needs_stripping(file):
3737
line = line.rstrip('\n')
3838
if line != line.rstrip():
3939
# contains trailing whitespace other than '\n'
40-
print(repr(line))
4140
return True
4241
return False
4342

update-ends.py

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -28,30 +28,22 @@
2828

2929
"""Update ends of markdown files."""
3030

31+
# Markdown and HTML links use / as a path separator so we need posixpath
32+
# for parsing them and we do need to replace / with os.sep when opening
33+
# the files.
34+
import posixpath
3135
import re
3236

3337
import common
3438

3539

36-
# Markdown and HTML links use / as a path separator so there's no need
37-
# for os.path, but we do need to replace / with os.sep when opening the
38-
# files.
39-
BASIC_END = """\
40+
END_TEMPLATE = """\
4041
You may use this tutorial freely at your own risk. See
41-
[LICENSE]({toplevel}LICENSE).
42+
[LICENSE]({license}).
4243
43-
[List of contents]({toplevel}README.md#list-of-contents)
44+
{extralinks}[List of contents]({readme}#{readmeheader})
4445
"""
4546

46-
CHAPTER_END = """\
47-
You may use this tutorial freely at your own risk. See
48-
[LICENSE](../LICENSE).
49-
50-
[Previous]({prev}) | [Next]({next}) |
51-
[List of contents](../README.md#{sectionname})
52-
"""
53-
54-
5547
CHAPTER_LINK_REGEX = r'^\d+\. \[.*\]\((.*\.md)\)$'
5648

5749

@@ -122,37 +114,46 @@ def main():
122114
print("Chapter files:")
123115
for prevpath, thispath, nextpath in zip(prevs, chapter_files, nexts):
124116
# the paths are like 'section/file.md'
125-
prevsection, prevfile = prevpath.split('/')
126-
thissection, thisfile = thispath.split('/')
127-
nextsection, nextfile = nextpath.split('/')
117+
prevsection, prevfile = posixpath.split(prevpath)
118+
thissection, thisfile = posixpath.split(thispath)
119+
nextsection, nextfile = posixpath.split(nextpath)
128120

129121
# make previous and next relative to this file
130122
if prevsection == thissection:
131123
# they are in the same place
132124
prev = prevfile
133125
elif prevsection == '.':
134126
# something from the top level
135-
prev = '../' + prevfile
127+
prev = posixpath.join('..', prevfile)
136128
else:
137129
# it comes from some other place
138-
prev = '../' + prevpath
130+
prev = posixpath.join('..', prevpath)
139131

140132
if nextsection == thissection:
141133
next_ = nextfile
142134
elif nextsection == '.':
143-
next_ = '../' + nextfile
135+
next_ = posixpath.join('..', nextfile)
144136
else:
145-
next_ = '../' + nextpath
137+
next_ = posixpath.join('..', nextpath)
146138

147-
end = CHAPTER_END.format(prev=prev, next=next_,
148-
sectionname=thissection)
139+
extralinks = "[Previous](%s) | [Next](%s) |\n" % (prev, next_)
140+
end = END_TEMPLATE.format(
141+
license='../LICENSE', readme='../README.md',
142+
extralinks=extralinks, readmeheader=thissection)
149143
update_end(thispath, end)
150144

151145
print()
152146

153147
print("Other files:")
154148
for filename in other_files:
155-
end = BASIC_END.format(toplevel='../'*filename.count('/'))
149+
# move to the top level as needed
150+
parts = ['..'] * filename.count('/')
151+
licenseparts = parts + ['LICENSE']
152+
readmeparts = parts + ['README.md']
153+
end = END_TEMPLATE.format(
154+
license=posixpath.join(*licenseparts),
155+
readme=posixpath.join(*readmeparts),
156+
extralinks="", readmeheader='list-of-contents')
156157
update_end(filename, end)
157158

158159

0 commit comments

Comments
 (0)