Remove weird hyphens from files
[lttng-docs.git] / tools / checkdocs.py
1 #!/usr/bin/env python3
2
3 # The MIT License (MIT)
4 #
5 # Copyright (c) 2014 Philippe Proulx <eepp.ca>
6 # Copyright (c) 2014 The LTTng Project <lttng.org>
7 #
8 # Permission is hereby granted, free of charge, to any person obtaining a copy
9 # of this software and associated documentation files (the "Software"), to deal
10 # in the Software without restriction, including without limitation the rights
11 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 # copies of the Software, and to permit persons to whom the Software is
13 # furnished to do so, subject to the following conditions:
14 #
15 # The above copyright notice and this permission notice shall be included in
16 # all copies or substantial portions of the Software.
17 #
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 # THE SOFTWARE.
25
26 import re
27 import os
28 import sys
29 from termcolor import colored
30
31
32 TOC_PATH = 'toc/docs.yml'
33 CONTENTS_ROOT_PATH = 'contents'
34
35
36 def _perror(filename, msg):
37 s = '{} {} {}'.format(filename, colored('Error:', 'red'),
38 colored(msg, 'red', attrs=['bold']))
39 print(s)
40
41
42 def _pwarn(filename, msg):
43 s = '{} {} {}'.format(filename, colored('Warning:', 'yellow'),
44 colored(msg, 'yellow', attrs=['bold']))
45 print(s)
46
47
48 def _get_files(root):
49 files = []
50
51 for dirpath, dirnames, filenames in os.walk(root):
52 for f in filenames:
53 files.append(os.path.join(dirpath, f))
54
55 return sorted(files)
56
57
58 def _get_toc_ids(path):
59 p = re.compile(r'id\s*:\s*(.+)$', flags=re.M)
60
61 with open(path) as f:
62 orig_ids = p.findall(f.read())
63
64 ids = set(orig_ids)
65
66 if len(ids) != len(orig_ids):
67 _perror(path, 'Duplicate IDs')
68 return None
69
70 return ids
71
72
73 def _check_file_links(toc_ids, path, c):
74 ilinkp = re.compile(r'\[[^\]]+\]\(([^)]+)\)', flags=re.M)
75 elinkp = re.compile(r'<a(?:\s+[^>]+|\s*)>')
76
77 ret = True
78
79 ilinks = ilinkp.findall(c)
80 elinks = elinkp.findall(c)
81
82 for link in ilinks:
83 if not link.startswith('#doc-'):
84 s = 'Internal link does not start with "#doc-": "{}"'.format(link)
85 _perror(path, s)
86 ret = False
87 continue
88
89 sid = link[5:]
90
91 if sid not in toc_ids:
92 _perror(path, 'Dead internal link: "{}"'.format(link))
93 ret = False
94
95 hrefp = re.compile(r'href="([^"]+)"')
96 classesp = re.compile(r'class="([^"]+)"')
97
98 for link in elinks:
99 href = hrefp.search(link)
100 classes = classesp.search(link)
101
102 if classes is None:
103 _pwarn(path, 'External link has no "ext" class: "{}"'.format(link))
104 classes = []
105 else:
106 classes = classes.group(1).split(' ')
107
108 if 'int' not in classes and 'ext' not in classes:
109 _pwarn(path, 'External link has no "ext" class: "{}"'.format(link))
110
111 if href is not None:
112 if href.group(1).startswith('#') and 'int' not in classes:
113 _pwarn(path, 'External link starts with #: "{}"'.format(href.group(1)))
114 else:
115 _perror(path, 'External link with no "href": "{}"'.format(link))
116 ret = False
117
118 return ret
119
120
121 def _check_contents(toc_ids, contents_files):
122 ret = True
123
124 for path in contents_files:
125 with open(path) as f:
126 c = f.read()
127
128 ret &= _check_file_links(toc_ids, path, c)
129
130 return ret
131
132
133 def _check_non_md(files):
134 ret = True
135
136 for f in files:
137 if not f.endswith('.md'):
138 _perror(f, 'Wrong, non-Markdown file')
139 ret = False
140
141 return ret
142
143
144 def checkdocs():
145 toc_ids = _get_toc_ids(TOC_PATH)
146
147 if toc_ids is None:
148 return False
149
150 contents_files = _get_files(CONTENTS_ROOT_PATH)
151
152 if not _check_non_md(contents_files):
153 return False
154
155 if not _check_contents(toc_ids, contents_files):
156 return False
157
158 return True
159
160
161 if __name__ == '__main__':
162 sys.exit(0 if checkdocs() else 1)
This page took 0.032098 seconds and 4 git commands to generate.