build_manual_gallery.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. ############################################################################
  4. #
  5. # MODULE: build_graphical_index
  6. # AUTHOR(S): Vaclav Petras <wenzeslaus gmail com>
  7. # PURPOSE: Build index gallery from images from all HTML files
  8. # COPYRIGHT: (C) 2015 by Vaclav Petras and the GRASS Development Team
  9. #
  10. # This program is free software under the GNU General Public
  11. # License (>=v2). Read the file COPYING that comes with GRASS
  12. # for details.
  13. #
  14. #############################################################################
  15. import os
  16. import sys
  17. import fnmatch
  18. import re
  19. from build_html import write_html_footer, grass_version, header1_tmpl
  20. output_name = 'manual_gallery.html'
  21. img_extensions = ['png', 'jpg', 'gif']
  22. img_patterns = ['*.' + extension for extension in img_extensions]
  23. # we don't want some images to show up
  24. # logos
  25. img_blacklist = ['grass_logo.png', 'grass_icon.png']
  26. # circles with numbers from helptext.html (unfortunate we have to list it here)
  27. # perhaps some general name ending would be good, like *_noindex.png
  28. img_blacklist.extend(['circle_{0}.png'.format(num) for num in range(1, 6)])
  29. year = os.getenv("VERSION_DATE")
  30. # other similar strings are in a different file
  31. # TODO: all HTML manual building needs refactoring (perhaps grass.tools?)
  32. header_graphical_index_tmpl = """\
  33. <link rel="stylesheet" href="grassdocs.css" type="text/css">
  34. <style>
  35. .img-list {
  36. list-style-type: none;
  37. margin: 0;
  38. padding: 0;
  39. text-align: center;
  40. }
  41. .img-list li {
  42. display: inline-block;
  43. position: relative;
  44. width: 7em;
  45. margin: 0;
  46. padding: 0.5em;
  47. }
  48. .img-list li:hover {
  49. background-color: #eee;
  50. }
  51. .img-list li img {
  52. float: left;
  53. max-width: 100%;
  54. background: white;
  55. }
  56. .img-list li span {
  57. text-align: center;
  58. }
  59. .img-list li a {
  60. color: initial;
  61. text-decoration: none;
  62. }
  63. .img-list li .name {
  64. margin: 0.1em;
  65. display: block;
  66. color: #409940;
  67. font-weight: normal;
  68. font-style: italic;
  69. font-size: 80%;
  70. }
  71. </style>
  72. </head>
  73. <body style="width: 99%">
  74. <div id="container">
  75. <a href="index.html"><img src="grass_logo.png" alt="GRASS logo"></a>
  76. <hr class="header">
  77. <h2>GRASS GIS manual gallery</h2>
  78. """
  79. def img_in_html(filename, imagename):
  80. # for some reason, calling search just once is much faster
  81. # than calling it on every line (time is spent in _compile)
  82. pattern = re.compile('<img .*src=.{0}.*>'.format(imagename))
  83. with open(filename) as file:
  84. if re.search(pattern, file.read()):
  85. return True
  86. return False
  87. def file_matches(filename, patterns):
  88. for pattern in patterns:
  89. if fnmatch.fnmatch(filename, pattern):
  90. return True
  91. return False
  92. def get_files(directory, patterns, exclude_patterns):
  93. files = []
  94. for filename in sorted(os.listdir(directory)):
  95. if file_matches(filename, patterns):
  96. if not file_matches(filename, exclude_patterns):
  97. files.append(filename)
  98. return files
  99. def remove_module_name(string, module):
  100. string = string.replace(module.replace('wxGUI.', 'g.gui.'), '')
  101. string = string.replace(module.replace('.', '_'), '') # using _
  102. string = string.replace(module.replace('.', ''), '') # using nothing
  103. string = string.replace(module, '') # using original dots
  104. return string
  105. def title_from_names(module_name, img_name):
  106. # we ignore the possibility of having extension at the end of image
  107. # so possibly r.out.png fails but image name should use _ anyway
  108. # strictly speaking, it could be also, e.g., index name
  109. for extension in img_extensions:
  110. img_name = img_name.replace('.' + extension, '')
  111. img_name = remove_module_name(img_name, module_name)
  112. img_name = img_name.replace('_', ' ')
  113. img_name = img_name.strip()
  114. if img_name:
  115. return "{name} ({desc})".format(name=module_name, desc=img_name)
  116. else:
  117. return "{name}".format(name=module_name)
  118. def get_module_name(filename):
  119. return filename.replace('.html', '')
  120. def main():
  121. html_dir = sys.argv[1]
  122. html_files = get_files(html_dir, ['*.html'],
  123. exclude_patterns=[output_name, '*_graphical.html', 'graphical_index.html'])
  124. img_html_files = {}
  125. for filename in os.listdir(html_dir):
  126. if filename in img_blacklist:
  127. continue
  128. if file_matches(filename, img_patterns):
  129. for html_file in html_files:
  130. if img_in_html(os.path.join(html_dir, html_file), filename):
  131. img_html_files[filename] = html_file
  132. # for now suppose one image per html
  133. with open(os.path.join(html_dir, output_name), 'w') as output:
  134. output.write(header1_tmpl.substitute(title="GRASS GIS %s Reference "
  135. "Manual: Manual gallery" % grass_version))
  136. output.write(header_graphical_index_tmpl)
  137. output.write('<ul class="img-list">\n')
  138. for image, html_file in sorted(img_html_files.items()):
  139. name = get_module_name(html_file)
  140. title = title_from_names(name, image)
  141. output.write(
  142. '<li>'
  143. '<a href="{html}" title="{title}">'
  144. '<img src="{img}">'
  145. '<span class="name">{name}</span>'
  146. '</a>'
  147. '</li>\n'
  148. .format(html=html_file, img=image, title=title, name=name))
  149. output.write('</ul>')
  150. write_html_footer(output, "index.html", year)
  151. if __name__ == '__main__':
  152. main()