build_manual_gallery.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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(
  123. html_dir,
  124. ["*.html"],
  125. exclude_patterns=[output_name, "*_graphical.html", "graphical_index.html"],
  126. )
  127. img_html_files = {}
  128. for filename in os.listdir(html_dir):
  129. if filename in img_blacklist:
  130. continue
  131. if file_matches(filename, img_patterns):
  132. for html_file in html_files:
  133. if img_in_html(os.path.join(html_dir, html_file), filename):
  134. img_html_files[filename] = html_file
  135. # for now suppose one image per html
  136. with open(os.path.join(html_dir, output_name), "w") as output:
  137. output.write(
  138. header1_tmpl.substitute(
  139. title="GRASS GIS %s Reference " "Manual: Manual gallery" % grass_version
  140. )
  141. )
  142. output.write(header_graphical_index_tmpl)
  143. output.write('<ul class="img-list">\n')
  144. for image, html_file in sorted(img_html_files.items()):
  145. name = get_module_name(html_file)
  146. title = title_from_names(name, image)
  147. output.write(
  148. "<li>"
  149. '<a href="{html}" title="{title}">'
  150. '<img src="{img}">'
  151. '<span class="name">{name}</span>'
  152. "</a>"
  153. "</li>\n".format(html=html_file, img=image, title=title, name=name)
  154. )
  155. output.write("</ul>")
  156. write_html_footer(output, "index.html", year)
  157. if __name__ == "__main__":
  158. main()