Pre-render website read pages
This commit is contained in:
parent
a47671e2af
commit
307094794f
|
|
@ -62,6 +62,7 @@ RUN set -eu; \
|
||||||
COPY httpd-php-fpm.conf /etc/apache2/conf.d/php-fpm.conf
|
COPY httpd-php-fpm.conf /etc/apache2/conf.d/php-fpm.conf
|
||||||
COPY opcache.ini /usr/local/etc/php/conf.d/zz-opcache.ini
|
COPY opcache.ini /usr/local/etc/php/conf.d/zz-opcache.ini
|
||||||
COPY php-fpm-runtime.conf /usr/local/etc/php-fpm.d/zz-runtime.conf
|
COPY php-fpm-runtime.conf /usr/local/etc/php-fpm.d/zz-runtime.conf
|
||||||
|
COPY render-static-pages.sh /usr/local/bin/render-static-pages
|
||||||
COPY start-website.sh /usr/local/bin/start-website
|
COPY start-website.sh /usr/local/bin/start-website
|
||||||
|
|
||||||
COPY . /var/www/localhost/htdocs/
|
COPY . /var/www/localhost/htdocs/
|
||||||
|
|
@ -74,10 +75,13 @@ RUN rm -f /var/www/localhost/htdocs/index.html && \
|
||||||
/var/log/apache2 \
|
/var/log/apache2 \
|
||||||
/var/www/localhost/htdocs/db \
|
/var/www/localhost/htdocs/db \
|
||||||
/tmp/website-lang && \
|
/tmp/website-lang && \
|
||||||
|
chmod 0755 /usr/local/bin/render-static-pages && \
|
||||||
|
/usr/local/bin/render-static-pages /var/www/localhost/htdocs && \
|
||||||
chown -R apache:apache \
|
chown -R apache:apache \
|
||||||
/run/apache2 \
|
/run/apache2 \
|
||||||
/var/log/apache2 \
|
/var/log/apache2 \
|
||||||
/var/www/localhost/htdocs/db \
|
/var/www/localhost/htdocs/db \
|
||||||
|
/var/www/localhost/htdocs/static-pages \
|
||||||
/tmp/website-lang && \
|
/tmp/website-lang && \
|
||||||
chmod 0755 /usr/local/bin/start-website
|
chmod 0755 /usr/local/bin/start-website
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/lang_helper.php';
|
require_once __DIR__ . '/lang_helper.php';
|
||||||
require_once __DIR__ . '/ideas_helper.php';
|
|
||||||
|
|
||||||
$activityKeys = [
|
$activityKeys = [
|
||||||
'blog_activity_1',
|
'blog_activity_1',
|
||||||
|
|
@ -80,8 +79,6 @@ $caseStudyCards = [
|
||||||
];
|
];
|
||||||
|
|
||||||
$treeHref = 'homelab-tree.php?lang=' . urlencode($lang);
|
$treeHref = 'homelab-tree.php?lang=' . urlencode($lang);
|
||||||
$ideaStatus = visitor_idea_clean((string) ($_GET['idea'] ?? ''), 20);
|
|
||||||
$visitorIdeas = visitor_ideas_read();
|
|
||||||
$giteaSourceBase = 'https://lab2025.duckdns.org/git/jv/my-homelab-configs/src/branch/main/';
|
$giteaSourceBase = 'https://lab2025.duckdns.org/git/jv/my-homelab-configs/src/branch/main/';
|
||||||
$stackSourceLinks = [
|
$stackSourceLinks = [
|
||||||
'blog_stack_1' => [
|
'blog_stack_1' => [
|
||||||
|
|
@ -814,7 +811,12 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="visitor-ideas" id="visitor-ideas">
|
<div class="visitor-ideas" id="visitor-ideas"
|
||||||
|
data-recent-title="<?php echo htmlspecialchars($text['blog_ideas_recent_title']); ?>"
|
||||||
|
data-status-thanks="<?php echo htmlspecialchars($text['blog_idea_status_thanks']); ?>"
|
||||||
|
data-status-invalid="<?php echo htmlspecialchars($text['blog_idea_status_invalid']); ?>"
|
||||||
|
data-status-slow="<?php echo htmlspecialchars($text['blog_idea_status_slow']); ?>"
|
||||||
|
data-status-error="<?php echo htmlspecialchars($text['blog_idea_status_error']); ?>">
|
||||||
<div class="section-heading">
|
<div class="section-heading">
|
||||||
<p class="section-kicker"
|
<p class="section-kicker"
|
||||||
data-translate data-key="blog_ideas_kicker"
|
data-translate data-key="blog_ideas_kicker"
|
||||||
|
|
@ -831,14 +833,6 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php if (in_array($ideaStatus, ['thanks', 'invalid', 'slow', 'error'], true)): ?>
|
|
||||||
<p class="idea-status idea-status-<?php echo htmlspecialchars($ideaStatus); ?>"
|
|
||||||
data-translate data-key="blog_idea_status_<?php echo htmlspecialchars($ideaStatus); ?>"
|
|
||||||
data-en="<?php echo htmlspecialchars($en['blog_idea_status_' . $ideaStatus]); ?>">
|
|
||||||
<?php echo $text['blog_idea_status_' . $ideaStatus]; ?>
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<form class="idea-form" action="save_idea.php" method="post">
|
<form class="idea-form" action="save_idea.php" method="post">
|
||||||
<input type="hidden" name="lang" value="<?php echo htmlspecialchars($lang); ?>">
|
<input type="hidden" name="lang" value="<?php echo htmlspecialchars($lang); ?>">
|
||||||
<label>
|
<label>
|
||||||
|
|
@ -866,25 +860,6 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<?php if ($visitorIdeas): ?>
|
|
||||||
<div class="visitor-idea-list">
|
|
||||||
<h4 data-translate data-key="blog_ideas_recent_title"
|
|
||||||
data-en="<?php echo htmlspecialchars($en['blog_ideas_recent_title']); ?>">
|
|
||||||
<?php echo $text['blog_ideas_recent_title']; ?>
|
|
||||||
</h4>
|
|
||||||
<?php foreach ($visitorIdeas as $visitorIdea): ?>
|
|
||||||
<article class="visitor-idea-card">
|
|
||||||
<p><?php echo nl2br(htmlspecialchars($visitorIdea['idea'])); ?></p>
|
|
||||||
<footer>
|
|
||||||
<span><?php echo htmlspecialchars($visitorIdea['name']); ?></span>
|
|
||||||
<time datetime="<?php echo htmlspecialchars($visitorIdea['created_at']); ?>">
|
|
||||||
<?php echo htmlspecialchars(substr($visitorIdea['created_at'], 0, 10)); ?>
|
|
||||||
</time>
|
|
||||||
</footer>
|
|
||||||
</article>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
@ -893,6 +868,7 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so
|
||||||
window.OTHER_PAGES = ['/index.php', '/cv.php', '/homelab-tree.php'];
|
window.OTHER_PAGES = ['/index.php', '/cv.php', '/homelab-tree.php'];
|
||||||
</script>
|
</script>
|
||||||
<script src="cv-theme.js"></script>
|
<script src="cv-theme.js"></script>
|
||||||
|
<script src="visitor-ideas.js"></script>
|
||||||
<?php require_once __DIR__ . '/partials/translation_ui.php'; ?>
|
<?php require_once __DIR__ . '/partials/translation_ui.php'; ?>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,27 @@
|
||||||
|
RewriteEngine On
|
||||||
|
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)lang=en(&|$)
|
||||||
|
RewriteRule ^/?(?:index\.php)?$ /static-pages/en/index.html [END]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)lang=en(&|$)
|
||||||
|
RewriteRule ^/?(cv|blog|demos|homelab-tree)\.php$ /static-pages/en/$1.html [END]
|
||||||
|
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)lang=nah(&|$)
|
||||||
|
RewriteRule ^/?(?:index\.php)?$ /static-pages/nah/index.html [END]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)lang=nah(&|$)
|
||||||
|
RewriteRule ^/?(cv|blog|demos|homelab-tree)\.php$ /static-pages/nah/$1.html [END]
|
||||||
|
|
||||||
|
RewriteCond %{QUERY_STRING} !(^|&)lang= [NC]
|
||||||
|
RewriteCond %{HTTP:Accept-Language} ^en [NC]
|
||||||
|
RewriteRule ^/?(?:index\.php)?$ /static-pages/en/index.html [END]
|
||||||
|
RewriteCond %{QUERY_STRING} !(^|&)lang= [NC]
|
||||||
|
RewriteCond %{HTTP:Accept-Language} ^en [NC]
|
||||||
|
RewriteRule ^/?(cv|blog|demos|homelab-tree)\.php$ /static-pages/en/$1.html [END]
|
||||||
|
|
||||||
|
RewriteCond %{QUERY_STRING} !(^|&)lang= [NC]
|
||||||
|
RewriteRule ^/?(?:index\.php)?$ /static-pages/nah/index.html [END]
|
||||||
|
RewriteCond %{QUERY_STRING} !(^|&)lang= [NC]
|
||||||
|
RewriteRule ^/?(cv|blog|demos|homelab-tree)\.php$ /static-pages/nah/$1.html [END]
|
||||||
|
|
||||||
<FilesMatch "\.php$">
|
<FilesMatch "\.php$">
|
||||||
SetHandler "proxy:fcgi://127.0.0.1:9000"
|
SetHandler "proxy:fcgi://127.0.0.1:9000"
|
||||||
</FilesMatch>
|
</FilesMatch>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
root="${1:-/var/www/localhost/htdocs}"
|
||||||
|
|
||||||
|
render_page() {
|
||||||
|
lang="$1"
|
||||||
|
source="$2"
|
||||||
|
output="$3"
|
||||||
|
request_uri="$4"
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$output")"
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
php -r '
|
||||||
|
parse_str($argv[1], $_GET);
|
||||||
|
$_SERVER["HTTP_ACCEPT_LANGUAGE"] = $argv[2];
|
||||||
|
$_SERVER["REQUEST_METHOD"] = "GET";
|
||||||
|
$_SERVER["REQUEST_URI"] = $argv[3];
|
||||||
|
$_SERVER["PHP_SELF"] = "/" . $argv[4];
|
||||||
|
chdir($argv[5]);
|
||||||
|
include $argv[5] . "/" . $argv[4];
|
||||||
|
' "lang=$lang" "$lang" "$request_uri" "$source" "$root" > "$output"
|
||||||
|
}
|
||||||
|
|
||||||
|
for lang in en nah; do
|
||||||
|
static_dir="$root/static-pages/$lang"
|
||||||
|
render_page "$lang" index.php "$static_dir/index.html" "/?lang=$lang"
|
||||||
|
render_page "$lang" cv.php "$static_dir/cv.html" "/cv.php?lang=$lang"
|
||||||
|
render_page "$lang" blog.php "$static_dir/blog.html" "/blog.php?lang=$lang"
|
||||||
|
render_page "$lang" demos.php "$static_dir/demos.html" "/demos.php?lang=$lang"
|
||||||
|
render_page "$lang" homelab-tree.php "$static_dir/homelab-tree.html" "/homelab-tree.php?lang=$lang"
|
||||||
|
done
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
(function () {
|
||||||
|
const root = document.getElementById('visitor-ideas');
|
||||||
|
if (!root) return;
|
||||||
|
|
||||||
|
const messages = {
|
||||||
|
thanks: root.dataset.statusThanks,
|
||||||
|
invalid: root.dataset.statusInvalid,
|
||||||
|
slow: root.dataset.statusSlow,
|
||||||
|
error: root.dataset.statusError,
|
||||||
|
};
|
||||||
|
|
||||||
|
const status = new URLSearchParams(window.location.search).get('idea');
|
||||||
|
if (status && messages[status]) {
|
||||||
|
const statusEl = document.createElement('p');
|
||||||
|
statusEl.className = `idea-status idea-status-${status}`;
|
||||||
|
statusEl.textContent = messages[status];
|
||||||
|
const form = root.querySelector('.idea-form');
|
||||||
|
root.insertBefore(statusEl, form || root.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addIdeaText(parent, text) {
|
||||||
|
String(text || '').split('\n').forEach((line, index) => {
|
||||||
|
if (index > 0) parent.appendChild(document.createElement('br'));
|
||||||
|
parent.appendChild(document.createTextNode(line));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderIdeas(ideas) {
|
||||||
|
const existing = root.querySelector('.visitor-idea-list');
|
||||||
|
if (existing) existing.remove();
|
||||||
|
if (!Array.isArray(ideas) || ideas.length === 0) return;
|
||||||
|
|
||||||
|
const list = document.createElement('div');
|
||||||
|
list.className = 'visitor-idea-list';
|
||||||
|
|
||||||
|
const heading = document.createElement('h4');
|
||||||
|
heading.textContent = root.dataset.recentTitle || 'Recent visitor ideas';
|
||||||
|
list.appendChild(heading);
|
||||||
|
|
||||||
|
ideas.forEach((idea) => {
|
||||||
|
const article = document.createElement('article');
|
||||||
|
article.className = 'visitor-idea-card';
|
||||||
|
|
||||||
|
const body = document.createElement('p');
|
||||||
|
addIdeaText(body, idea.idea);
|
||||||
|
article.appendChild(body);
|
||||||
|
|
||||||
|
const footer = document.createElement('footer');
|
||||||
|
const name = document.createElement('span');
|
||||||
|
name.textContent = idea.name || 'Anonymous visitor';
|
||||||
|
const time = document.createElement('time');
|
||||||
|
time.dateTime = idea.created_at || '';
|
||||||
|
time.textContent = String(idea.created_at || '').slice(0, 10);
|
||||||
|
footer.appendChild(name);
|
||||||
|
footer.appendChild(time);
|
||||||
|
article.appendChild(footer);
|
||||||
|
|
||||||
|
list.appendChild(article);
|
||||||
|
});
|
||||||
|
|
||||||
|
root.appendChild(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch('/visitor_ideas.php', { headers: { Accept: 'application/json' } })
|
||||||
|
.then((response) => (response.ok ? response.json() : { ideas: [] }))
|
||||||
|
.then((data) => renderIdeas(data.ideas))
|
||||||
|
.catch(() => renderIdeas([]));
|
||||||
|
})();
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/ideas_helper.php';
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
||||||
|
http_response_code(405);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
|
echo json_encode(
|
||||||
|
['ideas' => visitor_ideas_read()],
|
||||||
|
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
|
||||||
|
);
|
||||||
Loading…
Reference in New Issue