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