]> git.donarmstrong.com Git - lilypond.git/blob - buildscripts/add_html_footer.py
Add blacklist of non copied HTML files in translated offline docs
[lilypond.git] / buildscripts / add_html_footer.py
1 #!@PYTHON@
2
3 """
4 Print a nice footer.
5 """
6 import re
7 import os
8 import time
9
10 import langdefs
11
12 # This is to try to make the docball not too big with almost duplicate files
13 # see process_links()
14 non_copied_pages = ['Documentation/user/out-www/lilypond-big-page',
15                     'Documentation/user/out-www/lilypond-internals-big-page',
16                     'Documentation/user/out-www/music-glossary-big-page',
17                     'out-www/examples',
18                     'Documentation/topdocs/out-www/NEWS',
19                     'Documentation/topdocs/out-www/INSTALL',
20                     'Documentation/bibliography/out-www/index',
21                     'Documentation/out-www/THANKS',
22                     'Documentation/out-www/DEDICATION',
23                     'Documentation/topdocs/ou-www/AUTHORS']
24
25 header = r"""
26 """
27
28 footer = r'''
29 <div style="background-color: #e8ffe8; padding: 2; border: #c0ffc0 1px solid;">
30 <p>
31 <font size="-1">
32 This page is for %(package_name)s-%(package_version)s (%(branch_str)s). <br>
33 </font>
34 <address><font size="-1">
35 Report errors to <a href="%(mail_address_url)s">%(mail_address)s</a>.</font></address>
36 </p>
37 </div>
38 '''
39
40 mail_address = 'http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs'
41
42 header_tag = '<!-- header_tag -->'
43 footer_tag = '<!-- footer_tag -->'
44
45 def _ (s):
46     return s
47
48 language_available = _ ("Other languages: %s.") % "%(language_menu)s"
49 browser_language = _ ("Using <A HREF='%s'>automatic language selection</A>.") \
50            % "/web/about/browser-language"
51
52 LANGUAGES_TEMPLATE = '''\
53 <P>
54  %(language_available)s
55  <BR>
56  %(browser_language)s
57 </P>
58 ''' % vars ()
59
60
61 html_re = re.compile ('(.*?)(?:[.]([^/.]*))?[.]html$')
62 pages_dict = {}
63
64 def build_pages_dict (filelist):
65     """Build dictionnary of available translations of each page"""
66     global pages_dict
67     for f in filelist:
68         m = html_re.match (f)
69         if m:
70             g = m.groups()
71             if len (g) <= 1 or g[1] == None:
72                 e = ''
73             else:
74                 e = g[1]
75             if not g[0] in pages_dict.keys():
76                 pages_dict[g[0]] = [e]
77             else:
78                 pages_dict[g[0]].append (e)
79
80 def add_header (s):
81     """Add header (<BODY> and doctype)"""
82     if re.search (header_tag, s) == None:
83         body = '<BODY BGCOLOR=WHITE TEXT=BLACK>'
84         s = re.sub ('(?i)<body>', body, s)
85         if re.search ('(?i)<BODY', s):
86             s = re.sub ('(?i)<body[^>]*>', body + header, s, 1)
87         elif re.search ('(?i)<html', s):                
88             s = re.sub ('(?i)<html>', '<HTML>' + header, s, 1)
89         else:
90             s = header + s
91
92         s = header_tag + '\n' + s
93
94         if re.search ('(?i)<!DOCTYPE', s) == None:
95             doctype = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n'
96             s = doctype + s
97         return s
98
99 def info_external_ref_remove (s):
100     """Remove info's annoying's indication of referencing external document"""
101     return re.sub (' \((lilypond|lilypond-internals|music-glossary)\)</a>', '</a>', s)
102
103 def add_title (s):
104     # urg
105     # maybe find first node?
106     fallback_web_title = '-- --'
107     m = re.match ('.*?<title>(.*?)</title>', s, re.DOTALL)
108     if m:
109         fallback_web_title = m.group (1)
110     s = re.sub ('@WEB-TITLE@', fallback_web_title, s)
111     return s
112
113 info_nav_bar = re.compile (r'<div class="node">\s*<p>\s*<a name=".+?"></a>(.+?)<hr>\s*</div>', re.M | re.S)
114
115 def add_footer (s):
116     """add footer
117
118 also add navigation bar to bottom of Info HTML pages"""
119     m = info_nav_bar.search (s)
120     if m:
121         custom_footer = '<br><hr>\n<div class="node">\n<p>' + m.group (1) + '</div>\n' + footer
122     else:
123         custom_footer = footer
124     if re.search ('(?i)</body', s):
125         s = re.sub ('(?i)</body>', footer_tag + custom_footer + '\n' + '</BODY>', s, 1)
126     elif re.search ('(?i)</html', s):                
127         s = re.sub ('(?i)</html>', footer_tag + custom_footer + '\n' + '</HTML>', s, 1)
128     else:
129         s += footer_tag + custom_footer + '\n'
130     return s
131
132 def find_translations (prefix, lang_ext):
133     """find available translations of a page"""
134     available = []
135     missing = []
136     for l in langdefs.LANGUAGES:
137         e = l.webext
138         if lang_ext != e:
139             if e in pages_dict[prefix]:
140                 available.append (l)
141             elif lang_ext == '' and l.enabled and not prefix in non_copied_pages:
142                 # English version of missing translated pages will be written
143                 missing.append (e)
144     return available, missing
145
146 def process_links (s, prefix, lang_ext, file_name, missing, target):
147     page_flavors = {}
148     if target == 'online':
149         # Strip .html, .png suffix for auto language selection (content
150         # negotiation).  The menu must keep the full extension, so do
151         # this before adding the menu.
152         page_flavors[file_name] = re.sub (
153             '''(href|src)=[\'"]([^/][.]*[^.:\'"]*)(.html|.png)(#[^"\']*|)[\'"]''',
154             '\\1="\\2\\4"', s)
155     elif target == 'offline':
156         # in LANG doc index: don't rewrite .html suffixes as not all .LANG.html pages exist
157         # the doc index should be translated and contain the right links
158         if prefix == 'Documentation/out-www/index':
159             page_flavors[file_name] = s
160         elif lang_ext == '':
161             page_flavors[file_name] = s
162             for e in missing:
163                 page_flavors[langdefs.lang_file_name (prefix, e, '.html')] = re.sub (
164                     '''href=[\'"]([^/][.]*[^.:\'"]*)(.html)(#[^"\']*|)[\'"]''',
165                     'href="\\1.' + e + '\\2\\3"', s)
166         else:
167             page_flavors[file_name] = re.sub (
168                 '''href=[\'"]([^/][.]*[^.:\'"]*)(.html)(#[^"\']*|)[\'"]''',
169                 'href="\\1.' + lang_ext + '\\2\\3"', s)
170     return page_flavors
171
172 def add_menu (page_flavors, prefix, available):
173     language_menu = ''
174     for lang in available:
175         lang_file = lang.file_name (os.path.basename (prefix), '.html')
176         if language_menu != '':
177             language_menu += ', '
178         language_menu += '<a href="%s">%s</a>' % (lang_file, lang.name)
179
180     languages = ''
181     if language_menu:
182         languages = LANGUAGES_TEMPLATE % vars ()
183
184     # put language menu before '</body>' and '</html>' tags
185     for k in page_flavors.keys():
186         if re.search ('(?i)</body', page_flavors[k]):
187             page_flavors[k] = re.sub ('(?i)</body>', languages + '</BODY>', page_flavors[k], 1)
188         elif re.search ('(?i)</html', page_flavors[k]):                
189             page_flavors[k] = re.sub ('(?i)</html>', languages + '</HTML>', page_flavors[k], 1)
190         else:
191             page_flavors[k] += languages
192     return page_flavors
193
194
195 def add_html_footer (package_name = '',
196                      package_version = '',
197                      target = 'offline',
198                      name_filter = lambda s: s):
199     """Add header, footer to a number of HTML files
200
201     Arguments:
202      package_name=NAME         set package_name to NAME
203      package_version=VERSION   set package version to VERSION
204      targets=offline|online    set page processing depending on the target
205           offline is for reading HTML pages locally
206           online is for hosting the HTML pages on a website with content
207             negotiation
208      name_filter               a HTML file name filter
209     """
210     localtime = time.strftime ('%c %Z', time.localtime (time.time ()))
211
212     if re.search ("http://", mail_address):
213         mail_address_url = mail_address
214     else:
215         mail_address_url= 'mailto:' + mail_address
216
217     versiontup = package_version.split ('.')
218     branch_str = 'stable-branch'
219     if int ( versiontup[1]) %  2:
220         branch_str = 'development-branch'
221
222     for prefix, ext_list in pages_dict.items ():
223         for lang_ext in ext_list:
224             file_name = langdefs.lang_file_name (prefix, lang_ext, '.html')
225             in_f = open (file_name)
226             s = in_f.read()
227             in_f.close()
228
229             s = re.sub ('%', '%%', s)
230             s = add_header (s)
231             # seems to be no more needed
232             # s = info_external_ref_remove (s)
233
234             ### add footer
235             if re.search (footer_tag, s) == None:
236                 s = add_footer (s)
237                 available, missing = find_translations (prefix, lang_ext)
238                 page_flavors = process_links (s, prefix, lang_ext, file_name, missing, target)
239                 # Add menu after stripping: must not have autoselection for language menu.
240                 page_flavors = add_menu (page_flavors, prefix, available)
241             # urg, this stuff is oudated and seems useless, let's disable it
242             #else:
243             #    for e in [l.webext for l in langdefs.LANGUAGES]:
244             #        if not e in pages_dict[prefix]:
245             #            page_flavors[langdefs.lang_file_name (prefix, e, '.html')] = s
246
247             subst = globals ()
248             subst.update (locals())
249             for k in page_flavors.keys():
250                 page_flavors[k] = page_flavors[k] % subst
251
252                 out_f = open (name_filter (k), 'w')
253                 out_f.write (page_flavors[k])
254                 out_f.close()
255         # if the page is translated, a .en.html symlink is necessary for content negotiation
256         if target == 'online' and ext_list != ['']:
257             os.symlink (os.path.basename (prefix) + '.html', name_filter (prefix + '.en.html'))