#!/usr/bin/php CSS if ($config['css'] == true) { // Create CSS output directory if needed if (!file_exists(SITE . '/css')) mkdir(SITE . '/css', 0755); require ROOT . '/less.php/lib/Less/Autoloader.php'; Less_Autoloader::register(); $colorScheme = [ 'darkColor' => 'black', 'lightColor' => 'white', 'mainColor' => 'red', ]; $options = [ 'cache_dir' => SITE . '/css', 'compress' => true, ]; if (file_exists(SITE . '/style.less')) $lessFiles = [ROOT . '/style.less' => '', SITE . '/style.less' => '']; else $lessFiles = [ROOT . '/style.less' => '']; define('CSS_FILENAME', Less_Cache::Get($lessFiles, $options, $colorScheme)); } // Determine whether links need to use Onion or DNS function clearnetOrOnion($clearnet_url, $onion_url) { return (DESTINATION === 'onion') ? $onion_url : $clearnet_url; } $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(SITE . '/src', RecursiveDirectoryIterator::SKIP_DOTS)); foreach($files as $file) { $info = new SplFileInfo($file->getPathName()); if ($info->getType() !== 'file' OR !in_array($info->getExtension(), ['gmi', 'md', 'html'], true) OR str_starts_with($info->getPathname(), '.')) continue; $files_dates[$info->getPathname()] = $info->getMTime(); } asort($files_dates); ob_start(); ?> <?= $config['title'] ?> urn:publicid: ' . LF; ?> $last_mod) { $dest_page = str_replace('/src/', '/', $src_page); $page_content = file_get_contents($src_page); preg_match('/^# ?(?.*)$/Dm', $page_content, $matches); $title = $matches['title'] ?? NULL; $path_parts = pathinfo($dest_page); $base_filepath = $path_parts['dirname'] . '/' . $path_parts['filename']; if (!file_exists($dest_page) OR (filemtime($src_page) > filemtime($dest_page)) OR $opt['force']) { echo 'Compiling ' . $src_page . ' ' . date("Y-m-d H:i:s", $last_mod) . LF; // Create parent directory if needed if (!file_exists($path_parts['dirname'])) mkdir($path_parts['dirname'], 0755, true); // Execute PHP code ob_start(); eval('?>' . $page_content); file_put_contents($base_filepath . '.gmi', ob_get_contents()); ob_end_clean(); // Convert Gemtext to Markdown if ($path_parts['extension'] === 'gmi') { $gmilines = explode(LF, file_get_contents($base_filepath . '.gmi')); foreach ($gmilines as $key => $line) { if (str_starts_with($line, '=>')) { preg_match('/=> +(.[^ ]+)/', $line, $lnUrl); preg_match('/=> +.[^ ]+ +(.+)/', $line, $lnTitle); $urlPathParts = pathinfo(parse_url($lnUrl[1], PHP_URL_PATH)); // .gmi > .md for local links if (!str_contains($lnUrl[1], ':') AND $urlPathParts['extension'] === 'gmi') // If it's a local link $lnUrl[1] = $urlPathParts['dirname'] . '/' . $urlPathParts['filename'] . '.md'; $gmilines[$key] = '[' . ($lnTitle[1] ?? $lnUrl[1]) . '](' . $lnUrl[1] . ')'; } } $code = ''; foreach ($gmilines as $line) $code .= LF . $line; file_put_contents($base_filepath . '.md', $code); } // Compile Markdown to HTML $markdown = file_get_contents($base_filepath . '.md'); $process = proc_open('pandoc --fail-if-warnings -f markdown_phpextra-citations-native_divs-native_spans+abbreviations+hard_line_breaks+lists_without_preceding_blankline -t html --wrap none', [ 0 => ['pipe', 'r'], 1 => ['pipe', 'w'], ], $pipes); if (is_resource($process) !== true) exit('Can\'t spawn pandoc.' . PHP_EOL); fwrite($pipes[0], $markdown); fclose($pipes[0]); $pageContent = stream_get_contents($pipes[1]); fclose($pipes[1]); if (proc_close($process) !== 0) exit('pandoc failed.' . PHP_EOL); // .md > .html for local links $pageContent = preg_replace('#<a href="(?!.*:)(.*)\.md">#', '<a href="$1.html">', $pageContent); $relativePathToRoot = ''; for ($i = substr_count(str_replace(SITE, '', $path_parts['dirname']), '/') ; $i > 0 ; $i--) $relativePathToRoot .= '../'; ob_start(); ?> <!DOCTYPE html> <html lang="<?php preg_match('#\.([a-zA-Z-]{2,5})\.#', $path_parts['basename'], $file_lang); if (isset($file_lang[1])) { $lang = $file_lang[1]; } else { preg_match('#/([a-z]{2})(/|$)#', $path_parts['dirname'], $dir_lang); $lang = $dir_lang[1] ?? $config['default-lang']; } echo $lang ?? ''; ?>"> <head> <meta charset="utf-8"> <?php if (isset($title) AND isset($config['title'])) echo '<title>' . $title . ' ยท ' . $config['title'] . ''; else if (isset($title)) echo '' . $title . ''; else if (isset($config['title'])) echo '' . $config['title'] . ''; ?> '; if ($config['announce-feed']) echo '' . LF; if ($config['announce-css']) echo '' . LF; if (file_exists(SITE . '/head.inc.html')) echo file_get_contents(SITE . '/head.inc.html'); ?>
'; else echo $config['site-title']; ?>
' . $pageContent . ''; else echo '
' . $pageContent . '
'; if (file_exists(SITE . '/end.inc.html')) require SITE . '/end.inc.html'; echo ''; $pageContent = ob_get_clean(); if (extension_loaded('tidy')) { $pageContent = tidy_repair_string($pageContent, [ 'indent' => true, 'indent-spaces' => 4, 'output-xhtml' => true, 'wrap' => 0, ]); $pageContent = str_replace(' ', ' ', $pageContent); } file_put_contents($base_filepath . '.html', $pageContent); // Gzip compression exec('gzip --keep --fast --force ' . $base_filepath . '.html'); } $relative_addr = substr_replace($base_filepath . '.html', '', strpos($base_filepath, SITE), strlen(SITE)); // As of RFC 3151: A URN Namespace for Public Identifiers $public_id = 'urn:publicid:' . $config['id'] . str_replace('/', '%2F', $relative_addr); preg_match('#\(?.*)\#s', file_get_contents($base_filepath . '.html'), $match); $atom_entry_content = $match['content']; // Make relative links absolute $atom_entry_content = preg_replace_callback('# href=\"(?[^:"]+)\"#', function ($matches) { global $config; global $path_parts; return ' href="' . ($config['base-url'][0] ?? '') . substr($path_parts['dirname'], strlen(SITE)) . '/' . $matches['relative_url'] . '"'; }, $atom_entry_content); if (!in_array('draft', explode('.', $path_parts['basename']), true)) { ob_start(); ?> <?= $title ?> ' . LF; ?> ' . LF); if ($config['css'] == true) exec('gzip --keep --fast --force ' . SITE . '/css/' . CSS_FILENAME);