OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 # Example run from the server2/ directory: | |
7 # $ converter.py ../static/ ../../api templates/articles/ templates/intros/ | |
8 # templates/public/ static/images/ -r | |
9 | |
10 import optparse | |
11 import os | |
12 import re | |
13 import shutil | |
14 | |
15 IGNORED_FILES = [ | |
16 '404', | |
17 'api_index', | |
18 'experimental', | |
19 'samples', | |
20 'index' | |
21 ] | |
22 | |
23 def _UnixName(name): | |
24 """Returns the unix_style name for a given lowerCamelCase string. | |
25 Shamelessly stolen from json_schema_compiler/model.py. | |
26 """ | |
27 name = os.path.splitext(name.split('/')[-1])[0] | |
28 s1 = re.sub('([a-z])([A-Z])', r'\1_\2', name) | |
29 s2 = re.sub('([A-Z]+)([A-Z][a-z])', r'\1_\2', s1) | |
30 return s2.replace('.', '_').lower() | |
31 | |
32 def _ReadFile(filename): | |
33 with open(filename, 'r') as f: | |
34 return f.read() | |
35 | |
36 def _WriteFile(filename, data): | |
37 with open(filename, 'w+') as f: | |
38 f.write(data) | |
39 | |
40 def _MakeArticleTemplate(filename): | |
41 return '{{+partials.standard_article article:intros.%s}}' % filename | |
42 | |
43 def _MakeAPITemplate(filename): | |
44 return ('{{+partials.standard_api api:apis.%s intro:intros.%s}}' % | |
not at google - send to devlin
2012/07/31 22:25:46
some APIs don't have intros, like fileSystem
that
cduvall
2012/08/01 01:40:50
Done.
| |
45 (filename, filename)) | |
46 | |
47 def _FormatFile(contents, path, name, image_dest, replace, is_api): | |
48 # Copy all images referenced in the page. | |
49 for image in re.findall(r'src="\.\./images/([^"]*)"', contents): | |
50 if not replace and os.path.exists(os.path.join(image_dest, image)): | |
51 continue | |
52 if '/' in image: | |
53 try: | |
54 os.makedirs(os.path.join(image_dest, image.rsplit('/', 1)[0])) | |
55 except: | |
56 pass | |
57 shutil.copy( | |
58 os.path.join(path, os.pardir, 'images', image), | |
59 os.path.join(image_dest, image)) | |
60 contents = re.sub(r'<!--.*-->', r'', contents) | |
not at google - send to devlin
2012/07/31 22:25:46
I don't think we want to delete *all* comments. Ju
cduvall
2012/08/01 01:40:50
Done.
| |
61 contents = re.sub(r'\.\./images', r'{{static}}/images', contents) | |
62 if is_api: | |
63 contents = re.sub(r'<div.*id="pageData-name".*>.*</div>', r'', contents) | |
64 else: | |
65 contents = re.sub(r'<div.*id="pageData-name".*>(.*)</div>', | |
66 r'<h1 class="page_title">\1</h1>', | |
67 contents) | |
68 # Remove blank lines. | |
69 contents = '\n'.join([line for line in contents.split('\n') if line.strip()]) | |
70 | |
71 # Attempt to guess if the page has no title. | |
72 if '<h1' not in contents and not is_api: | |
73 title = _UnixName(name) | |
74 title = ' '.join([part[0].upper() + part[1:] for part in title.split('_')]) | |
75 contents = ('<h1 class="page_title">%s</h1>' % title) + contents | |
76 return contents | |
77 | |
78 def _MoveAllFiles(source_dir, | |
79 api_dir, | |
80 articles_dest, | |
81 intros_dest, | |
82 template_dest, | |
83 image_dest, | |
84 replace=False, | |
85 exclude_dir=None): | |
86 if exclude_dir is None: | |
87 exclude_files = [] | |
88 else: | |
89 exclude_files = [_UnixName(f) for f in os.listdir(exclude_dir)] | |
90 exclude_files.extend(IGNORED_FILES) | |
91 if replace: | |
92 _CleanAPIs(source_dir, api_dir, intros_dest, template_dest, exclude_files) | |
93 for file_ in os.listdir(source_dir): | |
94 if _UnixName(file_) in exclude_files or file_.startswith('.'): | |
95 continue | |
96 _MoveSingleFile(source_dir, | |
97 file_, | |
98 api_dir, | |
99 articles_dest, | |
100 intros_dest, | |
101 template_dest, | |
102 image_dest, | |
103 replace) | |
104 | |
105 def _CleanAPIs(source_dir, api_dir, intros_dest, template_dest, exclude): | |
106 source_files = set(_UnixName(f) for f in os.listdir(source_dir)) | |
107 api_files = set(_UnixName(f) for f in os.listdir(api_dir)) | |
108 intros_files = set(_UnixName(f) for f in os.listdir(intros_dest)) | |
109 to_delete = intros_files - source_files - set(exclude) | |
110 for filename in os.listdir(intros_dest): | |
111 if _UnixName(filename) in to_delete: | |
112 os.remove(os.path.join(intros_dest, filename)) | |
113 os.remove(os.path.join(template_dest, filename)) | |
114 | |
115 def _MoveSingleFile(source_dir, | |
116 source_file, | |
117 api_dir, | |
118 articles_dest, | |
119 intros_dest, | |
120 template_dest, | |
121 image_dest, | |
122 replace=False): | |
123 unix_name = _UnixName(source_file) | |
124 is_api = unix_name in [_UnixName(f) for f in os.listdir(api_dir)] | |
125 processed_name = os.path.splitext(source_file)[0].replace('.', '_') | |
126 static_data = _FormatFile(_ReadFile(os.path.join(source_dir, source_file)), | |
127 source_dir, | |
128 source_file, | |
129 image_dest, | |
130 replace, | |
131 is_api) | |
132 template_file = os.path.join(template_dest, processed_name + '.html') | |
133 if is_api: | |
134 template_data = _MakeAPITemplate(unix_name) | |
135 static_file = os.path.join(intros_dest, processed_name + '.html') | |
136 else: | |
137 template_data = _MakeArticleTemplate(unix_name) | |
138 static_file = os.path.join(articles_dest, processed_name + '.html') | |
139 if replace or not os.path.exists(template_file): | |
140 _WriteFile(template_file, template_data) | |
141 if replace or not os.path.exists(static_file): | |
142 _WriteFile(static_file, static_data) | |
143 | |
144 if __name__ == '__main__': | |
145 parser = optparse.OptionParser( | |
146 description='Converts static files from the old documentation system to ' | |
147 'the new one. If run without -f, all the files in |src| will ' | |
148 'be converted.', | |
149 usage='usage: %prog [options] static_src_dir [-f static_src_file] ' | |
150 'api_dir articles_dest intros_dest template_dest image_dest') | |
151 parser.add_option('-f', | |
152 '--file', | |
153 action='store_true', | |
154 default=False, | |
155 help='convert single file') | |
156 parser.add_option('-e', | |
157 '--exclude', | |
158 default=None, | |
159 help='exclude files matching the names in this dir') | |
160 parser.add_option('-r', | |
161 '--replace', | |
162 action='store_true', | |
163 default=False, | |
164 help='replace existing files') | |
165 (opts, args) = parser.parse_args() | |
166 if (not opts.file and len(args) != 6) or (opts.file and len(args) != 7): | |
167 parser.error('incorrect number of arguments.') | |
168 | |
169 if opts.file: | |
170 _MoveSingleFile(*args, replace=opts.replace) | |
171 else: | |
172 _MoveAllFiles(*args, replace=opts.replace, exclude_dir=opts.exclude) | |
OLD | NEW |