rakefile.rb 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. # Used to create a static website for the gems-science website.
  2. #
  3. # To use this rakefile, you need to install asciidoctor and rouge:
  4. #
  5. # * `gem install asciidoctor`
  6. # * `gem install rouge`
  7. #
  8. # Then use the rake tasks to first "build", "show" and "update"
  9. # the website.
  10. #
  11. # Note that the main website is built with one set of styles, and
  12. # the 'software' for the code with a slightly different set.
  13. CWD = File.expand_path(File.dirname(__FILE__))
  14. SRC = File.join(CWD, 'pages') # location of adoc files
  15. SOFTWARE = File.join(CWD, 'pages/software') # location of adoc files
  16. # -----------------------------------------------------------------------------
  17. # Definitions for pages and accessor methods for main website
  18. Page = Struct.new(:filename, :title, :date)
  19. PAGES = [ Page.new('index', "Genetically Evolving Models in Science", ''),
  20. Page.new('overview', "Overview", ''),
  21. Page.new('publications', "Publications", ''),
  22. Page.new('workshop', "Workshop: Computational Scientific Discovery in Social Sciences", '2023-05-21'),
  23. ]
  24. # Return page for given page filename
  25. def page filename
  26. PAGES.find {|p| p.filename == filename }
  27. end
  28. # -----------------------------------------------------------------------------
  29. # Apply asciidoctor on every file in SRC+SOFTWARE to create the .html shells
  30. # If update? is true, then first checks if .adoc file is a new file or
  31. # has newer time than its .html file, and only converts if so.
  32. def make_shells(update=false)
  33. [SRC, SOFTWARE].each do |dir|
  34. Dir.chdir(dir) do
  35. Dir.foreach('.') do |file|
  36. next unless file.end_with? 'adoc'
  37. if update
  38. target = file.sub(/adoc\Z/, 'html')
  39. if !File.exist?(target) or File.mtime(target) < File.mtime(file)
  40. puts "Updating file: #{file}"
  41. `asciidoctor -a source-highlighter=rouge -s #{file}`
  42. end
  43. else
  44. puts "Converting file: #{file}"
  45. `asciidoctor -a source-highlighter=rouge -s #{file}`
  46. end
  47. end
  48. end
  49. end
  50. end
  51. # -----------------------------------------------------------------------------
  52. #
  53. # Returns HTML header for given page_name
  54. # -- header should be for an actual page, in which case use title from PAGES
  55. # or use the page_name for title
  56. def header page_name
  57. title = if page(page_name)
  58. page(page_name).title
  59. else # for pages without entry in PAGES
  60. page_name
  61. end
  62. return <<END
  63. <html><head>
  64. <link rel="stylesheet" type="text/css" href="/styles/main-style.css">
  65. <link rel="stylesheet" type="text/css" href="/styles/syntax.css">
  66. <title>#{title} :: GEMS Project</title>
  67. </head>
  68. <body>
  69. <a class="pagetitle" href="/index.html">GEMS Project</a> <br> <br>
  70. <a href="/overview">Overview</a> |
  71. <a href="/publications">Publications</a> |
  72. <a href="/software">Software</a>
  73. <hr>
  74. <div class="content">
  75. <h1>#{title}</h1>
  76. END
  77. end
  78. # Returns HTML footer
  79. def footer
  80. "</body></html>"
  81. end
  82. # -----------------------------------------------------------------------------
  83. #
  84. def software_page_title title
  85. case title
  86. when "builder"
  87. "GEMS Package: builder"
  88. when "gems-logger"
  89. "GEMS Package: GEMS-Logger"
  90. when "gems-tk"
  91. "GEMS Package: GEMS/Tk"
  92. when "gpstats"
  93. "GEMS Package: gpstats"
  94. when "index"
  95. "GEMS Code Nodes"
  96. when "mini-gp"
  97. "GEMS Package: mini-gp"
  98. when "plotting"
  99. "How Do I Plot Graphs?"
  100. when "syntax-tree"
  101. "GEMS Package: syntax-tree"
  102. else
  103. "GEMS Code Notes :: #{title}"
  104. end
  105. end
  106. # Returns HTML header for given page_name
  107. def software_header title
  108. return <<END
  109. <!DOCTYPE html lang="en"><head>
  110. <meta charset="utf-8"/>
  111. <link rel="stylesheet" type="text/css" href="/styles/style.css">
  112. <link rel="stylesheet" type="text/css" href="/styles/syntax.css">
  113. <title>GEMS Code Notes :: #{title}</title>
  114. </head>
  115. <body class="article toc2 toc-left">
  116. <div id="header">
  117. <h1>#{software_page_title(title)}</h1>
  118. <div id="toc" class="toc2">
  119. <div id="toctitle">Contents</div>
  120. <ul class="sectlevel1">
  121. <li><a href="/software/index.html">Overview</a></li>
  122. <li>
  123. <li>GEMS Packages</li>
  124. <li>
  125. <ul class="sectlevel2">
  126. <li>- <a href="/software/builder">builder</a></li>
  127. <li>- <a href="/software/gems-logger">gems-logger</a></li>
  128. <li>- <a href="/software/gems-tk">gems/tk</a></li>
  129. <li>- <a href="/software/gpstats">gpstats</a></li>
  130. <li>- <a href="/software/mini-gp">mini-gp</a></li>
  131. <li>- <a href="/software/syntax-tree">syntax-tree</a></li>
  132. </ul>
  133. </li>
  134. <li>API Reference</li>
  135. <ul class="sectlevel2">
  136. <li>- <a href="/software/gems-api">GEMS</a></li>
  137. <li>- <a href="/software/gems-tk-api">GEMS/Tk</a></li>
  138. </ul>
  139. <li>
  140. </li>
  141. <li>
  142. </ul>
  143. </div>
  144. </div>
  145. <div id="content">
  146. END
  147. end
  148. # Returns HTML footer
  149. def software_footer
  150. return <<END
  151. <div id="footer">
  152. <div id="footer-text">
  153. Last updated #{Time.now.gmtime} - Peter Lane <a href="mailto:p.c.lane@herts.ac.uk">p.c.lane@herts.ac.uk</a>
  154. </div></body></html>
  155. END
  156. end
  157. # Works through files in SRC+SOFTWARE and makes a complete HTML page in 'site'
  158. # attaching the header and footer.
  159. def make_page_files
  160. # -- make main pages
  161. Dir.foreach(SRC) do |file|
  162. next unless file.end_with? 'html'
  163. puts "make page: #{file}"
  164. page_name = file.gsub('.html', '')
  165. page_dir = if page_name == 'index'
  166. 'site'
  167. else
  168. File.join('site', page_name)
  169. end
  170. Dir.mkdir(page_dir) unless Dir.exist?(page_dir)
  171. File.open(File.join(page_dir, 'index.html'), "w") do |site_file|
  172. # output header
  173. site_file.puts header(page_name)
  174. # if a dated page, output date
  175. if page(page_name).date != ''
  176. site_file.puts "#{page(page_name).date}"
  177. end
  178. # output shell
  179. IO.foreach(File.join(SRC, file)) do |line|
  180. site_file.puts line
  181. end
  182. site_file.puts "</div>" # close the main content
  183. # output footer
  184. site_file.puts footer
  185. end
  186. end
  187. # -- make software pages
  188. Dir.foreach(SOFTWARE) do |file|
  189. next unless file.end_with? 'html'
  190. puts "make page: #{file}"
  191. page_name = file.gsub('.html', '')
  192. page_dir = if page_name == 'index'
  193. 'site/software'
  194. else
  195. File.join('site/software', page_name)
  196. end
  197. Dir.mkdir(page_dir) unless Dir.exist?(page_dir)
  198. File.open(File.join(page_dir, 'index.html'), "w") do |site_file|
  199. # output header
  200. site_file.puts software_header(page_name)
  201. # output shell
  202. IO.foreach(File.join(SOFTWARE, file)) do |line|
  203. site_file.puts line
  204. end
  205. site_file.puts "</div>" # close the main content
  206. # output footer
  207. site_file.puts software_footer
  208. end
  209. end
  210. end
  211. # Creates html pages for all the pages in the SRC directory.
  212. # Each page.html is placed into page/index.html for page/ links!
  213. def make_pages
  214. Dir.mkdir('site') unless Dir.exist?('site')
  215. Dir.mkdir('site/software') unless Dir.exist?('site/software')
  216. make_page_files
  217. end
  218. # Create the sitemap.xml file, which lists all the main pages
  219. # TODO: when released, may want to add 'software'
  220. def make_sitemap
  221. File.open('site/sitemap.xml', 'w') do |f|
  222. f.puts "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>"
  223. f.puts "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:xhtml=\"http://www.w3.org/1999/xhtml\">"
  224. PAGES.each do |page|
  225. f.puts " <url>"
  226. if page.filename == "index"
  227. f.puts " <loc>/index.html</loc>"
  228. else
  229. f.puts " <loc>/#{page.filename}/index.html</loc>"
  230. end
  231. f.puts " </url>"
  232. end
  233. f.puts "</urlset>"
  234. end
  235. end
  236. # -----------------------------------------------------------------------------
  237. # Tasks
  238. desc 'build web site'
  239. task :build => [:clean] do
  240. make_shells
  241. make_pages
  242. make_sitemap
  243. cp_r 'downloads', 'site'
  244. cp_r 'images', 'site'
  245. cp_r 'styles', 'site'
  246. end
  247. task :clean do
  248. # `rm #{SRC}/*.html`
  249. # `rm #{SOFTWARE}/*.html`
  250. rm_rf 'site'
  251. end
  252. desc 'recreate the GEMS api documentation'
  253. task :gems_api do
  254. `sbcl --script build-api.lisp`
  255. end
  256. desc 'show web site - port 8000'
  257. task :show do
  258. Dir.chdir('site') do
  259. `ruby -run -ehttpd . -p8000`
  260. end
  261. end
  262. # update task
  263. # check time of .adoc vs .html and only convert if necessary
  264. desc 'update revised or new files only'
  265. task :update do
  266. make_shells true
  267. make_pages
  268. make_sitemap
  269. cp_r 'downloads', 'site'
  270. cp_r 'images', 'site'
  271. cp_r 'styles', 'site'
  272. end