My static website generator using poole https://www.xythobuz.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. import re
  2. import itertools
  3. import email.utils
  4. import os.path
  5. import time
  6. import codecs
  7. from datetime import datetime
  8. DEFAULT_LANG = "en"
  9. BASE_URL = "https://www.xythobuz.de"
  10. def lightgallery(links):
  11. print '<div class="lightgallery">'
  12. for l in links:
  13. link = img = alt = ""
  14. if len(l) == 3:
  15. link, img, alt = l
  16. else:
  17. link, alt = l
  18. x = link.rfind('.')
  19. img = link[:x] + '_small' + link[x:]
  20. print '<div class="border" data-src="' + link + '"><a href="' + link + '"><img class="pic" src="' + img + '" alt="' + alt + '"></a></div>'
  21. print '</div>'
  22. # -----------------------------------------------------------------------------
  23. # preconvert hooks
  24. # -----------------------------------------------------------------------------
  25. def hook_preconvert_anotherlang():
  26. MKD_PATT = r'\.(?:md|mkd|mdown|markdown)$'
  27. _re_lang = re.compile(r'^[\s+]?lang[\s+]?[:=]((?:.|\n )*)', re.MULTILINE)
  28. vpages = [] # Set of all virtual pages
  29. for p in pages:
  30. current_lang = DEFAULT_LANG # Default language
  31. langs = [] # List of languages for the current page
  32. page_vpages = {} # Set of virtual pages for the current page
  33. text_lang = re.split(_re_lang, p.source)
  34. text_grouped = dict(zip([current_lang,] + \
  35. [lang.strip() for lang in text_lang[1::2]], \
  36. text_lang[::2]))
  37. for lang, text in text_grouped.iteritems():
  38. spath = p.fname.split(os.path.sep)
  39. langs.append(lang)
  40. if lang == "en":
  41. filename = re.sub(MKD_PATT, "%s\g<0>" % "", p.fname).split(os.path.sep)[-1]
  42. else:
  43. filename = re.sub(MKD_PATT, ".%s\g<0>" % lang, p.fname).split(os.path.sep)[-1]
  44. vp = Page(filename, virtual=text)
  45. # Copy real page attributes to the virtual page
  46. for attr in p:
  47. if not vp.has_key(attr):
  48. vp[attr] = p[attr]
  49. # Define a title in the proper language
  50. vp["title"] = p["title_%s" % lang] \
  51. if p.has_key("title_%s" % lang) \
  52. else p["title"]
  53. # Keep track of the current lang of the virtual page
  54. vp["lang"] = lang
  55. # Fix post name if exists
  56. if vp.has_key("post"):
  57. if lang == "en":
  58. vp["post"] = vp["post"][:]
  59. else:
  60. vp["post"] = vp["post"][:-len(lang) - 1]
  61. page_vpages[lang] = vp
  62. # Each virtual page has to know about its sister vpages
  63. for lang, vpage in page_vpages.iteritems():
  64. vpage["lang_links"] = dict([(l, v["url"]) for l, v in page_vpages.iteritems()])
  65. vpage["other_lang"] = langs # set other langs and link
  66. vpages += page_vpages.values()
  67. pages[:] = vpages
  68. _COMPAT = """ case "%s":
  69. $loc = "%s/%s";
  70. break;
  71. """
  72. _COMPAT_404 = """ default:
  73. $loc = "%s";
  74. break;
  75. """
  76. def hook_preconvert_compat():
  77. fp = open(os.path.join(options.project, "output", "index.php"), 'w')
  78. fp.write("<?\n")
  79. fp.write("// Auto generated xyCMS compatibility index.php\n")
  80. fp.write("$loc = 'https://www.xythobuz.de/index.de.html';\n")
  81. fp.write("if (isset($_GET['p'])) {\n")
  82. fp.write(" if (isset($_GET['lang'])) {\n")
  83. fp.write(" $_GET['p'] .= 'EN';\n")
  84. fp.write(" }\n")
  85. fp.write(" switch($_GET['p']) {\n")
  86. for p in pages:
  87. if p.get("compat", "") != "":
  88. tmp = p["compat"]
  89. if p.get("lang", DEFAULT_LANG) == DEFAULT_LANG:
  90. tmp = tmp + "EN"
  91. fp.write(_COMPAT % (tmp, "https://www.xythobuz.de", p.url))
  92. fp.write("\n")
  93. fp.write(_COMPAT_404 % "/404.html")
  94. fp.write(" }\n")
  95. fp.write("}\n")
  96. fp.write("if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1') {\n")
  97. fp.write(" if (php_sapi_name() == 'cgi') {\n")
  98. fp.write(" header('Status: 301 Moved Permanently');\n")
  99. fp.write(" } else {\n")
  100. fp.write(" header('HTTP/1.1 301 Moved Permanently');\n")
  101. fp.write(" }\n")
  102. fp.write("}\n");
  103. fp.write("header('Location: '.$loc);\n")
  104. fp.write("?>")
  105. fp.close()
  106. _SITEMAP = """<?xml version="1.0" encoding="UTF-8"?>
  107. <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  108. %s
  109. </urlset>
  110. """
  111. _SITEMAP_URL = """
  112. <url>
  113. <loc>%s/%s</loc>
  114. <lastmod>%s</lastmod>
  115. <changefreq>%s</changefreq>
  116. <priority>%s</priority>
  117. </url>
  118. """
  119. def hook_preconvert_sitemap():
  120. date = datetime.strftime(datetime.now(), "%Y-%m-%d")
  121. urls = []
  122. for p in pages:
  123. urls.append(_SITEMAP_URL % (BASE_URL, p.url, date, p.get("changefreq", "monthly"), p.get("priority", "0.5")))
  124. fname = os.path.join(options.project, "output", "sitemap.xml")
  125. fp = open(fname, 'w')
  126. fp.write(_SITEMAP % "".join(urls))
  127. fp.close()
  128. # -----------------------------------------------------------------------------
  129. # postconvert hooks
  130. # -----------------------------------------------------------------------------
  131. _RSS = """<?xml version="1.0"?>
  132. <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  133. <channel>
  134. <title>%s</title>
  135. <link>%s</link>
  136. <atom:link href="%s" rel="self" type="application/rss+xml" />
  137. <description>%s</description>
  138. <language>en-us</language>
  139. <pubDate>%s</pubDate>
  140. <lastBuildDate>%s</lastBuildDate>
  141. <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  142. <generator>Poole</generator>
  143. %s
  144. </channel>
  145. </rss>
  146. """
  147. _RSS_ITEM = """
  148. <item>
  149. <title>%s</title>
  150. <link>%s</link>
  151. <description>%s</description>
  152. <pubDate>%s</pubDate>
  153. <guid>%s</guid>
  154. </item>
  155. """
  156. def hook_postconvert_rss():
  157. items = []
  158. posts = [p for p in pages if "post" in p] # get all blog post pages
  159. posts.sort(key=lambda p: p.date, reverse=True)
  160. posts = posts[:10]
  161. for p in posts:
  162. title = p.post
  163. link = "%s/%s" % (BASE_URL, p.url)
  164. desc = p.html.replace("href=\"img", "%s%s%s" % ("href=\"", BASE_URL, "/img"))
  165. desc = desc.replace("src=\"img", "%s%s%s" % ("src=\"", BASE_URL, "/img"))
  166. desc = htmlspecialchars(desc)
  167. date = time.mktime(time.strptime("%s 12" % p.date, "%Y-%m-%d %H"))
  168. date = email.utils.formatdate(date)
  169. items.append(_RSS_ITEM % (title, link, desc, date, link))
  170. items = "".join(items)
  171. title = "xythobuz.de Blog"
  172. link = "%s/blog.html" % BASE_URL
  173. feed = "%s/rss.xml" % BASE_URL
  174. desc = htmlspecialchars("xythobuz Electronics & Software Projects")
  175. date = email.utils.formatdate()
  176. rss = _RSS % (title, link, feed, desc, date, date, items)
  177. fp = codecs.open(os.path.join(output, "rss.xml"), "w", "utf-8")
  178. fp.write(rss)
  179. fp.close()
  180. _COMPAT_MOB = """ case "%s":
  181. $loc = "%s/%s";
  182. break;
  183. """
  184. _COMPAT_404_MOB = """ default:
  185. $loc = "%s";
  186. break;
  187. """
  188. def hook_postconvert_mobilecompat():
  189. directory = os.path.join(output, "mobile")
  190. if not os.path.exists(directory):
  191. os.makedirs(directory)
  192. fp = codecs.open(os.path.join(directory, "index.php"), "w", "utf-8")
  193. fp.write("<?\n")
  194. fp.write("// Auto generated xyCMS compatibility mobile/index.php\n")
  195. fp.write("$loc = 'https://www.xythobuz.de/index.de.html';\n")
  196. fp.write("if (isset($_GET['p'])) {\n")
  197. fp.write(" if (isset($_GET['lang'])) {\n")
  198. fp.write(" $_GET['p'] .= 'EN';\n")
  199. fp.write(" }\n")
  200. fp.write(" switch($_GET['p']) {\n")
  201. for p in pages:
  202. if p.get("compat", "") != "":
  203. tmp = p["compat"]
  204. if p.get("lang", DEFAULT_LANG) == DEFAULT_LANG:
  205. tmp = tmp + "EN"
  206. fp.write(_COMPAT_MOB % (tmp, "https://www.xythobuz.de", re.sub(".html", ".html", p.url)))
  207. fp.write("\n")
  208. fp.write(_COMPAT_404_MOB % "/404.mob.html")
  209. fp.write(" }\n")
  210. fp.write("}\n")
  211. fp.write("if ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1') {\n")
  212. fp.write(" if (php_sapi_name() == 'cgi') {\n")
  213. fp.write(" header('Status: 301 Moved Permanently');\n")
  214. fp.write(" } else {\n")
  215. fp.write(" header('HTTP/1.1 301 Moved Permanently');\n")
  216. fp.write(" }\n")
  217. fp.write("}\n");
  218. fp.write("header('Location: '.$loc);\n")
  219. fp.write("?>")
  220. fp.close()
  221. def hook_postconvert_size():
  222. file_ext = '|'.join(['pdf', 'zip', 'rar', 'ods', 'odt', 'odp', 'doc', 'xls', 'ppt', 'docx', 'xlsx', 'pptx', 'exe', 'brd', 'mp3', 'mp4', 'plist'])
  223. def matched_link(matchobj):
  224. try:
  225. path = matchobj.group(1)
  226. if path.startswith("http") or path.startswith("//") or path.startswith("ftp"):
  227. return '<a href=\"%s\">%s</a>' % (matchobj.group(1), matchobj.group(3))
  228. elif path.startswith("/"):
  229. path = path.strip("/")
  230. path = os.path.join("static/", path)
  231. size = os.path.getsize(path)
  232. if size >= (1024 * 1024):
  233. return "<a href=\"%s\">%s</a>&nbsp;(%.1f MiB)" % (matchobj.group(1), matchobj.group(3), size / (1024.0 * 1024.0))
  234. elif size >= 1024:
  235. return "<a href=\"%s\">%s</a>&nbsp;(%d KiB)" % (matchobj.group(1), matchobj.group(3), size // 1024)
  236. else:
  237. return "<a href=\"%s\">%s</a>&nbsp;(%d Byte)" % (matchobj.group(1), matchobj.group(3), size)
  238. except:
  239. print "Unable to estimate file size for %s" % matchobj.group(1)
  240. return '<a href=\"%s\">%s</a>' % (matchobj.group(1), matchobj.group(3))
  241. _re_url = '<a href=\"([^\"]*?\.(%s))\">(.*?)<\/a>' % file_ext
  242. for p in pages:
  243. p.html = re.sub(_re_url, matched_link, p.html)