feat: dynamic ish terminal preview
This commit is contained in:
+32
-1
@@ -62,13 +62,44 @@ export const extractHeadings = (htmlContent) => {
|
||||
return headings;
|
||||
};
|
||||
|
||||
const leadingTerminalPreviewHeading = /^\s*<h1\b[^>]*\bid=(["'])terminal-preview\1[^>]*>[\s\S]*?<\/h1>/i;
|
||||
|
||||
const terminalPreviewBounds = (htmlContent) => {
|
||||
if (!htmlContent || typeof htmlContent !== "string") return null;
|
||||
|
||||
const heading = htmlContent.match(leadingTerminalPreviewHeading);
|
||||
if (!heading) return null;
|
||||
|
||||
const contentAfterHeading = htmlContent.slice(heading[0].length);
|
||||
const nextArticleHeading = contentAfterHeading.search(/<h[1-6]\b/i);
|
||||
if (nextArticleHeading === -1) return null;
|
||||
|
||||
const leadingArticleWhitespace = contentAfterHeading
|
||||
.slice(0, nextArticleHeading)
|
||||
.match(/\s*$/)?.[0] || "";
|
||||
|
||||
return {
|
||||
preview: contentAfterHeading.slice(0, nextArticleHeading),
|
||||
article: leadingArticleWhitespace + contentAfterHeading.slice(nextArticleHeading)
|
||||
};
|
||||
};
|
||||
|
||||
export const extractTerminalPreview = (htmlContent) => terminalPreviewBounds(htmlContent)?.preview || "";
|
||||
|
||||
export const removeTerminalPreview = (htmlContent) => {
|
||||
if (!htmlContent || typeof htmlContent !== "string") return "";
|
||||
return terminalPreviewBounds(htmlContent)?.article || htmlContent;
|
||||
};
|
||||
|
||||
export const filters = {
|
||||
postDate,
|
||||
isoDate,
|
||||
limit,
|
||||
filterTagList,
|
||||
readingTime,
|
||||
extractHeadings
|
||||
extractHeadings,
|
||||
extractTerminalPreview,
|
||||
removeTerminalPreview
|
||||
};
|
||||
|
||||
export default filters;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<!-- Left Sticky Sidebar: Document Outline & Telemetry -->
|
||||
<aside class="article-sidebar" aria-label="Article Sidebar">
|
||||
<!-- Dynamic Table of Contents -->
|
||||
{% set headings = content | extractHeadings %}
|
||||
{% set headings = (content | removeTerminalPreview) | extractHeadings %}
|
||||
{% if headings.length > 0 %}
|
||||
<div class="sidebar-tile">
|
||||
<div class="sidebar-heading">
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
<div class="stat-row">
|
||||
<span>DURATION:</span>
|
||||
<span class="stat-val">{{ content | readingTime(readingTime) }}</span>
|
||||
<span class="stat-val">{{ (content | removeTerminalPreview) | readingTime(readingTime) }}</span>
|
||||
</div>
|
||||
{% if difficulty %}
|
||||
<div class="stat-row">
|
||||
@@ -90,7 +90,7 @@
|
||||
<time datetime="{{ date | isoDate }}">{{ date | postDate }}</time>
|
||||
</span>
|
||||
<span>•</span>
|
||||
<span class="meta-item">{{ content | readingTime(readingTime) }}</span>
|
||||
<span class="meta-item">{{ (content | removeTerminalPreview) | readingTime(readingTime) }}</span>
|
||||
{% if difficulty %}
|
||||
<span>•</span>
|
||||
<span class="meta-item" style="color: var(--accent-amber);">DIFFICULTY: {{ difficulty }}</span>
|
||||
@@ -99,7 +99,7 @@
|
||||
</header>
|
||||
|
||||
<div class="markdown-prose">
|
||||
{{ content | safe }}
|
||||
{{ content | removeTerminalPreview | safe }}
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
@@ -32,21 +32,23 @@
|
||||
{{ featured.data.excerpt }}
|
||||
</p>
|
||||
|
||||
<!-- Terminal Code Preview Snippet -->
|
||||
<div class="terminal-code-box">
|
||||
<div class="code-titlebar">
|
||||
<span class="code-title">
|
||||
<span style="color: var(--accent-cyan);">></span>
|
||||
<span>init_cluster.sh</span>
|
||||
</span>
|
||||
<span>POSIX sh</span>
|
||||
</div>
|
||||
<div class="code-content">
|
||||
<pre><code class="language-bash"># System initialization and node health check
|
||||
./cluster.sh --verify-nodes
|
||||
curl -s https://api.local/healthz | jq .status</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% if featured.data.terminal == true %}
|
||||
{% set terminalPreview = featured.templateContent | extractTerminalPreview %}
|
||||
{% if terminalPreview %}
|
||||
<div class="terminal-code-box terminal-preview-box">
|
||||
<div class="code-titlebar">
|
||||
<span class="code-title">
|
||||
<span style="color: var(--accent-cyan);">></span>
|
||||
<span>TERMINAL PREVIEW</span>
|
||||
</span>
|
||||
<span>MARKDOWN</span>
|
||||
</div>
|
||||
<div class="terminal-preview-content">
|
||||
{{ terminalPreview | safe }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<div class="featured-cta-row">
|
||||
<div class="tag-cluster">
|
||||
|
||||
@@ -65,6 +65,35 @@
|
||||
font-family: var(--font-code);
|
||||
}
|
||||
|
||||
.terminal-preview-box {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.terminal-preview-content {
|
||||
padding: 14px 16px;
|
||||
color: var(--text-primary);
|
||||
font-size: 0.82rem;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.terminal-preview-content > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.terminal-preview-content > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.terminal-preview-content pre {
|
||||
margin: 10px 0;
|
||||
padding: 10px 12px;
|
||||
overflow-x: auto;
|
||||
background-color: var(--bg-surface);
|
||||
border: var(--border-width) solid var(--border-color);
|
||||
border-radius: var(--border-radius-sm);
|
||||
font-family: var(--font-code);
|
||||
}
|
||||
|
||||
/* Syntax Highlighting Tokens (Prism / 11ty Syntax Highlight) */
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
|
||||
Reference in New Issue
Block a user