Hypertext sites generator
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.

242 lines
6.5 KiB

  1. #!/usr/bin/php
  2. <?php
  3. if (php_sapi_name() !== "cli")
  4. exit("Must be run from CLI");
  5. // Initialization
  6. define("FIND", "/usr/bin/find");
  7. define("GZIP", "/usr/bin/gzip");
  8. define("ROOT", dirname($_SERVER['SCRIPT_FILENAME']));
  9. if (isset($argv[1]))
  10. define("SITE", $argv[1]);
  11. else
  12. define("SITE", getcwd());
  13. if (isset($argv[2]))
  14. define("DESTINATION", $argv[2]);
  15. else
  16. define("DESTINATION", "local");
  17. if (file_exists(SITE . "/config.ini"))
  18. $config = parse_ini_file(SITE . "/config.ini");
  19. if (!isset($config['trueBlack']))
  20. $config['trueBlack'] = false;
  21. if (!isset($config['siteTitle']))
  22. $config['siteTitle'] = "Site";
  23. if (!isset($config['css']))
  24. $config['css'] = true;
  25. if (!isset($config['header']))
  26. $config['header'] = true;
  27. if (!isset($config['centerIndex']))
  28. $config['centerIndex'] = false;
  29. if (!isset($config['defaultLang']))
  30. $config['defaultLang'] = "en";
  31. // Less > CSS
  32. // Create CSS output directory if needed
  33. if (!file_exists(SITE . "/css"))
  34. mkdir(SITE . "/css", 0755);
  35. require ROOT . "/less.php/lib/Less/Autoloader.php";
  36. Less_Autoloader::register();
  37. $colorScheme = array(
  38. "darkColor" => "#2a2a2a",
  39. "darkerColor" => "#222222",
  40. "lightColor" => "white",
  41. "lightlessColor" => "#eeeeee",
  42. "mainColor" => "red",
  43. );
  44. if ($config['trueBlack']) {
  45. $colorScheme['darkColor'] = "#000000";
  46. $colorScheme['darkerColor'] = "#000000";
  47. }
  48. $options = array(
  49. 'cache_dir' => SITE . '/css',
  50. 'compress' => true,
  51. );
  52. if (file_exists(SITE . "/style.less"))
  53. $lessFiles = array(ROOT . '/style.less' => '', SITE . '/style.less' => '');
  54. else
  55. $lessFiles = array(ROOT . '/style.less' => '');
  56. define("CSS_FILENAME", Less_Cache::Get($lessFiles, $options, $colorScheme));
  57. // URLs don't end with .html on the Antopie website
  58. function formerUrlLocale($page) {
  59. if (DESTINATION === "dns" OR DESTINATION === "onion") {
  60. echo $page;
  61. } else {
  62. echo $page . ".html";
  63. }
  64. }
  65. // Determine whether links need to use Onion or DNS
  66. function clearnetOrOnion($clearnetUrl, $onionUrl) {
  67. if (DESTINATION === "onion") {
  68. return $onionUrl;
  69. } else {
  70. return $clearnetUrl;
  71. }
  72. }
  73. exec(FIND . " " . SITE . "/src -name '*.gmi' -o -name '*.md'", $pages);
  74. foreach ($pages as $page) {
  75. $pathParts = pathinfo(str_replace("/src", "", $page));
  76. // Create parent directory if needed
  77. if (!file_exists($pathParts['dirname']))
  78. mkdir($pathParts['dirname'], 0755, true);
  79. // Execute PHP code
  80. ob_start();
  81. eval("?>" . file_get_contents($page));
  82. file_put_contents($pathParts['dirname'] . "/" . $pathParts['basename'], ob_get_contents());
  83. ob_end_clean();
  84. // Convert Gemtext to Markdown
  85. if ($pathParts['extension'] === "gmi") {
  86. $gmilines = explode("\n", file_get_contents($pathParts['dirname'] . "/" . $pathParts['basename']));
  87. if (substr($gmilines[0], 0, 2) === "# ")
  88. $title = substr($gmilines[0], 2);
  89. else
  90. $title = NULL;
  91. foreach ($gmilines as $key => $line) {
  92. if (substr($line, 0, 2) === "=>") {
  93. preg_match("/=> +(.[^ ]+)/", $line, $lnUrl);
  94. preg_match("/=> +.[^ ]+ +(.+)/", $line, $lnTitle);
  95. // Escape Markdown special characters
  96. $mdSpecial = array("[", "]", "(", ")");
  97. $htmlEntities = array("&#91;", "&#93;", "&#40;", "&#41;");
  98. $lnUrl[1] = str_replace($mdSpecial, $htmlEntities, $lnUrl[1]);
  99. $urlPathParts = pathinfo(parse_url($lnUrl[1], PHP_URL_PATH));
  100. // .gmi > .md for local links
  101. if (!str_contains($lnUrl[1], ":") AND $urlPathParts['extension'] === "gmi") // If it's a local link
  102. $lnUrl[1] = $urlPathParts['dirname'] . "/" . $urlPathParts['filename'] . ".md";
  103. if (isset($lnTitle[1])) {
  104. $lnTitle[1] = str_replace($mdSpecial, $htmlEntities, $lnTitle[1]);
  105. $gmilines[$key] = "[" . $lnTitle[1] . "](" . $lnUrl[1] . ")";
  106. } else {
  107. $gmilines[$key] = "[" . $lnUrl[1] . "](" . $lnUrl[1] . ")";
  108. }
  109. }
  110. }
  111. $code = "";
  112. foreach ($gmilines as $line) {
  113. $code = $code . "\n" . $line;
  114. }
  115. file_put_contents($pathParts['dirname'] . "/" . $pathParts['filename'] . ".md", $code);
  116. }
  117. // Compile Markdown to HTML with Parsedown
  118. require_once ROOT . "/parsedown/Parsedown.php";
  119. require_once ROOT . "/parsedown-extra/ParsedownExtra.php";
  120. $Parsedown = new ParsedownExtra;
  121. $Parsedown = $Parsedown->setUrlsLinked(false);
  122. $Parsedown = $Parsedown->setMarkupEscaped(false);
  123. $Parsedown = $Parsedown->setBreaksEnabled(true);
  124. $pageContent = $Parsedown->text(file_get_contents($pathParts['dirname'] . "/" . $pathParts['filename'] . ".md"));
  125. // .md > .html for local links
  126. $pageContent = preg_replace('#<a href="(?!.*:)(.*)\.md">#', '<a href="$1.html">', $pageContent);
  127. // Add header and footer to HTML
  128. ob_start();
  129. ?>
  130. <!DOCTYPE html>
  131. <html lang="<?php
  132. preg_match("#\.([a-zA-Z-]{2,5})\.#", $pathParts['basename'], $lang);
  133. if (isset($lang[1]))
  134. echo $lang[1];
  135. else
  136. echo $config['defaultLang'];
  137. ?>">
  138. <head>
  139. <meta charset="UTF-8">
  140. <title><?php
  141. if (isset($title) AND !is_null($title))
  142. echo $title . " · " . $config['siteTitle'];
  143. else
  144. echo $config['siteTitle'];
  145. ?></title>
  146. <meta name="viewport" content="width=device-width, initial-scale=1">
  147. <?php if ($config['css']) { ?>
  148. <link type="text/css" rel="stylesheet" media="screen" href="/css/<?= CSS_FILENAME ?>">
  149. <?php } ?>
  150. <?php
  151. if (file_exists(SITE . "/head.inc.html"))
  152. echo file_get_contents(SITE . "/head.inc.html");
  153. ?>
  154. </head>
  155. <body>
  156. <?php
  157. if ($config['header']) {
  158. ?>
  159. <header>
  160. <a id="lienHeader" href="/">
  161. <?php
  162. if (file_exists(SITE . "/img/logo.webp"))
  163. echo '<img src="img/logo.webp" ' . getimagesize(SITE . "/img/logo.webp")[3] . ' alt="' . $config['siteTitle'] . '" />';
  164. else
  165. echo $config['siteTitle'];
  166. ?>
  167. </a>
  168. </header>
  169. <?php
  170. }
  171. ?>
  172. <?php
  173. if ($config['centerIndex'] AND $pathParts['filename'] === "index") {
  174. echo '<div class="centered">';
  175. } else {
  176. echo "<main>";
  177. }
  178. echo $pageContent;
  179. if ($config['centerIndex'] AND $pathParts['filename'] === "index") {
  180. echo "</div>";
  181. } else {
  182. echo "</main>";
  183. }
  184. if (file_exists(SITE . "/end.inc.html"))
  185. require SITE . "/end.inc.html";
  186. echo "</body></html>";
  187. file_put_contents($pathParts['dirname'] . "/" . $pathParts['filename'] . ".html", ob_get_contents());
  188. ob_end_clean();
  189. // Gzip compression
  190. exec(GZIP . " --keep --fast --force " . $pathParts['dirname'] . "/" . $pathParts['filename'] . ".html");
  191. }
  192. exec(GZIP . " --keep --fast --force " . SITE . "/css/" . CSS_FILENAME);