#!/usr/bin/php
getPathName());
$src = $node_info->getPathname();
if (str_starts_with($src, SITE . '/target'))
continue;
$target = str_replace(SITE, SITE . '/target', $src);
$path_parts_src = pathinfo($src);
$path_parts_target = pathinfo($target);
if (strstr($src, '/.') !== false AND !str_ends_with($src, '/.htaccess')) // Skip hidden nodes (except for .htaccess)
continue;
if ($node_info->getType() !== 'file')
continue;
if (in_array('draft', explode('.', $path_parts_target['basename']), true))
continue;
if (!file_exists($path_parts_target['dirname'])) // Create parent directory if needed
mkdir($path_parts_target['dirname'], 0755, true);
copy($src, $target);
if ($node_info->getExtension() !== 'md')
continue;
$base_filepath_src = $path_parts_src['dirname'] . '/' . $path_parts_src['filename'];
$base_filepath_target = $path_parts_target['dirname'] . '/' . $path_parts_target['filename'];
$content = file_get_contents($src);
preg_match('/^# (?
.*)$/Dm', $content, $matches);
$title = $matches['title'] ?? NULL;
preg_match('#\.(?[a-z]{2})\.md#', $path_parts_src['basename'], $matches);
$lang = $matches['lang'] ?? $config['default-lang'] ?? exit('no language found for ' . $src . LF);
if (!file_exists($base_filepath_target . '.html') OR (filemtime($src) > filemtime($base_filepath_target . '.html')) OR $opt['force']) {
echo 'Compiling ' . $src . ' ' . date("Y-m-d H:i:s", $node_info->getMTime()) . LF;
// Execute PHP code
ob_start();
eval('?>' . $content);
$content = ob_get_clean();
// Convert Gemtext to Markdown
if ($path_parts_target['extension'] === 'gmi' OR $path_parts_target['extension'] === 'md') {
$content = preg_replace_callback(
'/^=>\h*(?\S+)(:?\h+(?\V+))?$/m',
function ($matches) {
if (!str_contains($matches['addr'], ':') AND str_ends_with($matches['addr'], '.gmi'))
$matches['addr'] = substr($matches['addr'], 0, -3) . 'md';
return '[' . ($matches['title'] ?? $matches['addr']) . '](' . $matches['addr'] . ')';
},
$content,
);
}
// Compile Markdown to HTML
$process = proc_open('pandoc --fail-if-warnings --section-divs -f markdown-citations-native_divs-native_spans+abbreviations+hard_line_breaks+lists_without_preceding_blankline+multiline_tables+fenced_divs+bracketed_spans+markdown_attribute -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], $content);
fclose($pipes[0]);
$content = stream_get_contents($pipes[1]);
fclose($pipes[1]);
if (proc_close($process) !== 0)
exit('pandoc failed.' . PHP_EOL);
// .md > .html for local links
$content = preg_replace('/ href="([^:"]+)\.md"/', ' href="$1.html"', $content);
$relative_root_path = str_repeat('../', substr_count(str_replace(SITE . '/target', '', $path_parts_target['dirname']), '/'));
ob_start();
?>
' . $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']) {
if (file_exists(SITE . '/style.css'))
echo ' ' . LF;
echo ' ' . LF;
}
if (file_exists(SITE . '/head.inc.html'))
echo file_get_contents(SITE . '/head.inc.html');
?>
' . file_get_contents(SITE . '/header.inc.php'));
if ($config['center-index'] AND $path_parts_target['filename'] === 'index')
echo '' . $content . '
';
else
echo '' . $content . '';
if (file_exists(SITE . '/end.inc.html'))
require SITE . '/end.inc.html';
echo '';
$content = ob_get_clean();
if (extension_loaded('tidy')) {
$content = tidy_repair_string($content, [
'indent' => true,
'indent-spaces' => 4,
'output-xhtml' => true,
'wrap' => 0,
]);
$content = str_replace(' ', ' ', $content);
}
file_put_contents($base_filepath_target . '.html', $content);
// Gzip compression
exec('gzip --keep --fast --force ' . $base_filepath_target . '.html');
}
$relative_addr = substr_replace($base_filepath_src . '.html', '', strpos($base_filepath_src, 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_target . '.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_target;
return ' href="' . ($config['base-url'][0] ?? '') . substr($path_parts_target['dirname'], strlen(SITE)) . '/' . $matches['relative_url'] . '"';
}, $atom_entry_content);
ob_start();
?>
= $title ?>
= $public_id ?>
= date('c', $node_info->getMTime()) ?>
' . LF;
?>
= htmlspecialchars($atom_entry_content) ?>
$unused) {
if ($level === 0)
continue;
$dir = implode('/', array_slice(explode('/', $relative_addr), 0, $level)) . '/';
$last_update = $node_info->getMTime();
$dirs_entries_per_lang['all'][$dir] = ($dirs_entries_per_lang['all'][$dir] ?? '') . $atom_entry;
$dirs_entries_per_lang[$lang][$dir] = ($dirs_entries_per_lang[$lang][$dir] ?? '') . $atom_entry;
if (!isset($dirs_last_update['all'][$dir]) OR $last_update > $dirs_last_update['all'][$dir])
$dirs_last_update['all'][$dir] = $last_update;
if (!isset($dirs_last_update[$lang][$dir]) OR $last_update > $dirs_last_update[$lang][$dir])
$dirs_last_update[$lang][$dir] = $last_update;
}
}
foreach ($dirs_entries_per_lang as $lang => $dirs_entries) {
foreach ($dirs_entries as $dir => $entries) {
ob_start();
?>
= ($config['title'] ?? '') . (($dir !== '/') ? ' ' . $dir : '') ?>
urn:publicid:= $config['id'] . str_replace('/', '%2F', $dir) ?>
' . LF;
?>
= date('c', $dirs_last_update[$lang][$dir]) ?>
= $config['author'] ?? '' ?>
' . LF);
}
}
if ($config['announce-css'])
copy(ROOT . '/style.css', SITE . '/target/mkht-php.css');