feat: initial release of pengzhan.dev personal editorial blog platform
- Editorial web platform built with Node.js, Express, EJS, and Vanilla CSS - Markdown content engine with YAML frontmatter, bilingual variants, and hot-reload watcher - Unified SQLite with FTS5 search indexing, query logging, and schema filters - Centered editorial post layout with margin-docked left TOC and mobile bottom sheet - WordPress-grade comment system with moderation dashboard and bulk operations under /guanli - Complete SEO suite (JSON-LD structured data, RSS/Atom feeds, XML sitemap, robots.txt) - CI/CD workflows for linting, security audits (Gitleaks), automated tests, and Docker releases
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
<%- include('../partials/head', { pageType: 'search' }) %>
|
||||
|
||||
<div class="content-container">
|
||||
<div class="search-hero" style="margin-bottom: 2rem;">
|
||||
<h1 style="font-size: 2.5rem; margin-bottom: 1.5rem; font-family: var(--font-serif);">Search</h1>
|
||||
|
||||
<form action="/search" method="GET" class="search-form-minimal" id="search-form">
|
||||
<div class="search-input-wrapper">
|
||||
<svg class="search-icon-svg" viewBox="0 0 24 24"><path d="M23.809 21.646l-6.205-6.205c1.167-1.605 1.857-3.579 1.857-5.711 0-5.365-4.365-9.73-9.731-9.73-5.365 0-9.73 4.365-9.73 9.73 0 5.366 4.365 9.73 9.73 9.73 2.034 0 3.923-.627 5.487-1.698l6.238 6.238 2.354-2.354zm-20.955-11.916c0-3.792 3.085-6.877 6.877-6.877s6.877 3.085 6.877 6.877-3.085 6.877-6.877 6.877c-3.793 0-6.877-3.085-6.877-6.877z"/></svg>
|
||||
<input
|
||||
type="search"
|
||||
id="search-input"
|
||||
name="q"
|
||||
value="<%= query %>"
|
||||
class="search-input-sleek"
|
||||
placeholder="Search..."
|
||||
autocomplete="off"
|
||||
autofocus
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Sleek Discovery & Recommended Searches -->
|
||||
<div class="search-discovery-pills" style="margin-top: 1.25rem;">
|
||||
<div class="search-pills-grid">
|
||||
<% (recommended.dynamicPills || []).forEach(pill => { %>
|
||||
<button type="button" class="pill search-pill-btn" data-query="<%= pill.query %>">
|
||||
<%= pill.label %>
|
||||
</button>
|
||||
<% }) %>
|
||||
|
||||
<% (recommended.customPills || []).forEach(pill => { %>
|
||||
<button type="button" class="pill search-pill-btn" data-query="<%= pill.query %>">
|
||||
<%= pill.label %>
|
||||
</button>
|
||||
<% }) %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search Results -->
|
||||
<% if (query) { %>
|
||||
<div class="search-results-section" style="margin-top: 2.5rem; border-top: 1px solid var(--color-border); padding-top: 2rem;">
|
||||
<div style="font-family: var(--font-sans); font-size: 0.95rem; color: var(--color-text-muted); margin-bottom: 1.5rem;">
|
||||
<%= searchData.total %> result<%= searchData.total === 1 ? '' : 's' %> for "<%= query %>"
|
||||
</div>
|
||||
|
||||
<% if (searchData.results.length > 0) { %>
|
||||
<div class="search-results-list">
|
||||
<% searchData.results.forEach(res => { %>
|
||||
<article class="search-result-item" style="margin-bottom: 2rem; padding-bottom: 1.5rem; border-bottom: 1px solid var(--color-surface-soft);">
|
||||
<h2 style="font-size: 1.45rem; margin-bottom: 0.35rem; font-family: var(--font-serif);">
|
||||
<a href="/<%= res.post.slug %><%= res.post.lang && res.post.lang !== 'en' && !res.post.isDefault ? `/${res.post.lang}` : '' %>" style="color: var(--color-text-main); text-decoration: none;">
|
||||
<%= res.post.title %>
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
<div class="post-card-meta" style="margin-bottom: 0.5rem; font-size: 0.82rem; color: var(--color-text-muted);">
|
||||
<time><%= res.post.date.toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) %></time>
|
||||
<span class="meta-sep">—</span>
|
||||
<span>by <%= res.post.author %></span>
|
||||
<% if (res.post.category) { %>
|
||||
<span>in <%= res.post.category %></span>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<% if (res.snippet) { %>
|
||||
<p class="search-snippet" style="font-size: 0.95rem; color: var(--color-text-secondary); line-height: 1.6;">
|
||||
<%- res.snippet %>
|
||||
</p>
|
||||
<% } %>
|
||||
</article>
|
||||
<% }) %>
|
||||
</div>
|
||||
<% } else { %>
|
||||
<p style="color: var(--color-text-muted); padding: 2rem 0; font-size: 1.05rem;">
|
||||
No articles found matching your query.
|
||||
</p>
|
||||
<% } %>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
<%- include('../partials/foot', { pageType: 'search' }) %>
|
||||
Reference in New Issue
Block a user