优化文章排版
This commit is contained in:
@@ -160,6 +160,320 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================
|
||||
文章页(简洁大气)
|
||||
========================================= */
|
||||
|
||||
.single-article-page {
|
||||
padding: 46px 0 72px;
|
||||
}
|
||||
|
||||
.single-article-shell {
|
||||
max-width: 1320px;
|
||||
}
|
||||
|
||||
.single-article {
|
||||
width: 100%;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.single-article-header {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.single-article-kicker {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 24px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.single-article-kicker-link {
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
font-size: 1.08rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
.single-article-kicker-link:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.single-article-title {
|
||||
margin: 0;
|
||||
font-size: clamp(2.3rem, 4.7vw, 5rem);
|
||||
line-height: 1.1;
|
||||
letter-spacing: -0.02em;
|
||||
color: var(--text-primary);
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.single-article-meta {
|
||||
margin-top: 28px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
align-items: baseline;
|
||||
column-gap: 16px;
|
||||
color: var(--text-secondary);
|
||||
font-family: var(--font-sans);
|
||||
font-size: 0.94rem;
|
||||
max-width: 980px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.single-article-meta-item {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.single-article-meta-label {
|
||||
color: var(--text-secondary);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.single-article-meta-value {
|
||||
color: var(--text-primary);
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 600;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.single-article-body {
|
||||
width: 100%;
|
||||
max-width: 1080px;
|
||||
margin: 52px auto 0;
|
||||
color: var(--text-primary);
|
||||
font-size: clamp(1.14rem, 1.2vw, 1.28rem);
|
||||
line-height: 1.82;
|
||||
font-family: "Times New Roman", Times, "Nimbus Roman No9 L", "Noto Sans SC", "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", var(--font-sans);
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.single-article-body > * {
|
||||
margin: 0 0 1.25em;
|
||||
}
|
||||
|
||||
.single-article-body h2,
|
||||
.single-article-body h3,
|
||||
.single-article-body h4 {
|
||||
margin-top: 1.7em;
|
||||
line-height: 1.35;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.single-article-body h2 {
|
||||
font-size: clamp(1.45rem, 1.6vw, 2rem);
|
||||
}
|
||||
|
||||
.single-article-body h3 {
|
||||
font-size: clamp(1.2rem, 1.2vw, 1.55rem);
|
||||
}
|
||||
|
||||
.single-article-body a {
|
||||
color: var(--text-primary);
|
||||
text-decoration-thickness: 1.5px;
|
||||
text-decoration-color: color-mix(in srgb, var(--color-primary) 70%, transparent);
|
||||
}
|
||||
|
||||
.single-article-body a:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.single-article-body blockquote {
|
||||
margin: 1.5em 0;
|
||||
padding: 0.2em 0 0.2em 1.1em;
|
||||
border-left: 3px solid var(--border-default);
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.single-article-body img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.single-article-body pre {
|
||||
padding: 16px;
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-sm);
|
||||
background: color-mix(in srgb, var(--bg-surface) 92%, transparent);
|
||||
overflow: auto;
|
||||
line-height: 1.45;
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
|
||||
.single-article-body code {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.9em;
|
||||
background: color-mix(in srgb, var(--bg-surface) 92%, transparent);
|
||||
border-radius: 4px;
|
||||
padding: 0.12em 0.35em;
|
||||
}
|
||||
|
||||
.single-article-tags {
|
||||
width: 100%;
|
||||
max-width: 1080px;
|
||||
margin: 30px auto 0;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid var(--border-default);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.single-article-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 24px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: 999px;
|
||||
text-decoration: none;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.78rem;
|
||||
background: color-mix(in srgb, var(--bg-card) 88%, transparent);
|
||||
}
|
||||
|
||||
.single-article-tag:hover {
|
||||
color: var(--color-primary);
|
||||
border-color: var(--color-primary);
|
||||
}
|
||||
|
||||
.single-related {
|
||||
max-width: 1180px;
|
||||
margin: 62px auto 0;
|
||||
}
|
||||
|
||||
.single-divider {
|
||||
border-top: 1px solid var(--border-default);
|
||||
}
|
||||
|
||||
.single-related-title {
|
||||
margin: 44px 0 24px;
|
||||
color: var(--text-primary);
|
||||
font-size: clamp(1.8rem, 2vw, 2.5rem);
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.single-related-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.single-related-card {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.single-related-card-title {
|
||||
margin: 0;
|
||||
font-size: clamp(1.2rem, 1.2vw, 1.75rem);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.single-related-card-title a {
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.single-related-card-title a:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.single-related-card-excerpt {
|
||||
margin: 12px 0 0;
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.66;
|
||||
font-size: 1rem;
|
||||
font-family: "Times New Roman", Times, "Nimbus Roman No9 L", "Noto Sans SC", "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", var(--font-sans);
|
||||
}
|
||||
|
||||
.single-related-card-link {
|
||||
margin-top: 16px;
|
||||
display: inline-block;
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
font-size: 1.02rem;
|
||||
}
|
||||
|
||||
.single-related-card-link:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.single-related-empty {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.single-article-comments {
|
||||
max-width: 900px;
|
||||
margin: 64px auto 0;
|
||||
}
|
||||
|
||||
@media (max-width: 980px) {
|
||||
.single-article-page {
|
||||
padding: 34px 0 56px;
|
||||
}
|
||||
|
||||
.single-article-body {
|
||||
margin-top: 42px;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
.single-related-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.single-article-kicker {
|
||||
gap: 14px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.single-article-meta {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px 14px;
|
||||
margin-top: 18px;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.single-article-body {
|
||||
margin-top: 30px;
|
||||
font-size: 1.02rem;
|
||||
line-height: 1.72;
|
||||
}
|
||||
|
||||
.single-related {
|
||||
margin-top: 44px;
|
||||
}
|
||||
|
||||
.single-related-title {
|
||||
margin-top: 34px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.single-related-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.single-article-comments {
|
||||
margin-top: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================================
|
||||
GitHub 风格博客
|
||||
========================================= */
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var TITLE_SELECTOR = ".single-article-title";
|
||||
var MAX_LINES = 2;
|
||||
var MIN_FONT_SIZE = 12;
|
||||
var MAX_FONT_SIZE = 92;
|
||||
var SEARCH_STEPS = 16;
|
||||
|
||||
function getLineHeightPx(element) {
|
||||
var computed = window.getComputedStyle(element);
|
||||
var lineHeight = computed.lineHeight;
|
||||
var fontSize = parseFloat(computed.fontSize) || 16;
|
||||
|
||||
if (lineHeight && lineHeight.indexOf("px") > -1) {
|
||||
return parseFloat(lineHeight);
|
||||
}
|
||||
|
||||
if (lineHeight === "normal") {
|
||||
return fontSize * 1.2;
|
||||
}
|
||||
|
||||
var ratio = parseFloat(lineHeight);
|
||||
if (Number.isFinite(ratio)) {
|
||||
return ratio * fontSize;
|
||||
}
|
||||
|
||||
return fontSize * 1.2;
|
||||
}
|
||||
|
||||
function getLineCount(element) {
|
||||
var lineHeightPx = getLineHeightPx(element);
|
||||
if (!lineHeightPx) {
|
||||
return 0;
|
||||
}
|
||||
return element.getBoundingClientRect().height / lineHeightPx;
|
||||
}
|
||||
|
||||
function setFontSize(element, size) {
|
||||
element.style.fontSize = size.toFixed(2) + "px";
|
||||
}
|
||||
|
||||
function fitsWithinLines(element, size) {
|
||||
setFontSize(element, size);
|
||||
return getLineCount(element) <= MAX_LINES + 0.01;
|
||||
}
|
||||
|
||||
function fitTitle(title) {
|
||||
if (!title) {
|
||||
return;
|
||||
}
|
||||
|
||||
var header = title.closest(".single-article-header") || title.parentElement || title;
|
||||
if (!header || header.getBoundingClientRect().width <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
title.style.fontSize = "";
|
||||
var computedSize = parseFloat(window.getComputedStyle(title).fontSize) || 48;
|
||||
|
||||
var low = MIN_FONT_SIZE;
|
||||
var high = Math.min(MAX_FONT_SIZE, Math.max(computedSize * 1.8, computedSize + 8));
|
||||
|
||||
while (high < MAX_FONT_SIZE && fitsWithinLines(title, high)) {
|
||||
high = Math.min(MAX_FONT_SIZE, high + 8);
|
||||
if (high === MAX_FONT_SIZE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var best = low;
|
||||
for (var i = 0; i < SEARCH_STEPS; i += 1) {
|
||||
var mid = (low + high) / 2;
|
||||
if (fitsWithinLines(title, mid)) {
|
||||
best = mid;
|
||||
low = mid;
|
||||
} else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fitsWithinLines(title, best)) {
|
||||
while (best > MIN_FONT_SIZE && !fitsWithinLines(title, best)) {
|
||||
best -= 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
setFontSize(title, Math.max(MIN_FONT_SIZE, best - 0.05));
|
||||
}
|
||||
|
||||
function initSingleTitleFitter() {
|
||||
var title = document.querySelector(TITLE_SELECTOR);
|
||||
if (!title) {
|
||||
return;
|
||||
}
|
||||
|
||||
var scheduled = false;
|
||||
var scheduleFit = function () {
|
||||
if (scheduled) {
|
||||
return;
|
||||
}
|
||||
scheduled = true;
|
||||
window.requestAnimationFrame(function () {
|
||||
scheduled = false;
|
||||
fitTitle(title);
|
||||
});
|
||||
};
|
||||
|
||||
scheduleFit();
|
||||
window.addEventListener("resize", scheduleFit, { passive: true });
|
||||
window.addEventListener("pageshow", scheduleFit);
|
||||
|
||||
if ("ResizeObserver" in window) {
|
||||
var resizeObserver = new ResizeObserver(scheduleFit);
|
||||
resizeObserver.observe(title);
|
||||
var header = title.closest(".single-article-header");
|
||||
if (header) {
|
||||
resizeObserver.observe(header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initSingleTitleFitter);
|
||||
} else {
|
||||
initSingleTitleFitter();
|
||||
}
|
||||
})();
|
||||
+148
@@ -81,6 +81,10 @@ function itstudio_enqueue_scripts() {
|
||||
wp_enqueue_script('itstudio-theme-toggle', get_template_directory_uri() . '/assets/js/theme-toggle.js', array(), '1.0.0', true);
|
||||
wp_enqueue_script('itstudio-lang-toggle', get_template_directory_uri() . '/assets/js/lang-toggle.js', array(), '1.0.0', true);
|
||||
wp_enqueue_script('itstudio-main', get_template_directory_uri() . '/assets/js/main.js', array(), '1.0.0', true);
|
||||
|
||||
if (is_singular(array('post', 'announcement', 'news'))) {
|
||||
wp_enqueue_script('itstudio-single-title-fit', get_template_directory_uri() . '/assets/js/single-title-fit.js', array(), '1.0.0', true);
|
||||
}
|
||||
}
|
||||
add_action('wp_enqueue_scripts', 'itstudio_enqueue_scripts');
|
||||
|
||||
@@ -484,6 +488,146 @@ function itstudio_get_post_excerpt_chars($post_id, $limit = 200) {
|
||||
return wp_html_excerpt($excerpt, $limit, '...');
|
||||
}
|
||||
|
||||
function itstudio_is_probably_bot_request() {
|
||||
$user_agent = strtolower(trim((string) ($_SERVER['HTTP_USER_AGENT'] ?? '')));
|
||||
if ($user_agent === '') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$bot_signatures = array(
|
||||
'bot',
|
||||
'spider',
|
||||
'crawl',
|
||||
'slurp',
|
||||
'headless',
|
||||
'preview',
|
||||
'facebookexternalhit',
|
||||
'discordbot',
|
||||
'telegrambot',
|
||||
'linkedinbot',
|
||||
'applebot',
|
||||
'googlebot',
|
||||
'bingbot',
|
||||
'wget',
|
||||
'curl',
|
||||
'python-requests',
|
||||
'postmanruntime',
|
||||
);
|
||||
|
||||
foreach ($bot_signatures as $signature) {
|
||||
if (strpos($user_agent, $signature) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$purpose = strtolower((string) ($_SERVER['HTTP_PURPOSE'] ?? ''));
|
||||
$sec_purpose = strtolower((string) ($_SERVER['HTTP_SEC_PURPOSE'] ?? ''));
|
||||
$x_moz = strtolower((string) ($_SERVER['HTTP_X_MOZ'] ?? ''));
|
||||
if (strpos($purpose, 'prefetch') !== false || strpos($sec_purpose, 'prefetch') !== false || $x_moz === 'prefetch') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function itstudio_get_view_cookie_name() {
|
||||
return 'itstudio_viewed_posts';
|
||||
}
|
||||
|
||||
function itstudio_read_view_cookie_map() {
|
||||
$cookie_name = itstudio_get_view_cookie_name();
|
||||
$raw_cookie = isset($_COOKIE[$cookie_name]) ? wp_unslash((string) $_COOKIE[$cookie_name]) : '';
|
||||
if ($raw_cookie === '') {
|
||||
return array();
|
||||
}
|
||||
|
||||
$decoded = json_decode($raw_cookie, true);
|
||||
if (!is_array($decoded)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$clean = array();
|
||||
foreach ($decoded as $post_id => $timestamp) {
|
||||
$post_id = (int) $post_id;
|
||||
$timestamp = (int) $timestamp;
|
||||
if ($post_id > 0 && $timestamp > 0) {
|
||||
$clean[(string) $post_id] = $timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
return $clean;
|
||||
}
|
||||
|
||||
function itstudio_write_view_cookie_map($map, $window_seconds) {
|
||||
if (!headers_sent()) {
|
||||
$cookie_name = itstudio_get_view_cookie_name();
|
||||
$expire_at = time() + max(DAY_IN_SECONDS, (int) $window_seconds * 2);
|
||||
$path = defined('COOKIEPATH') && COOKIEPATH ? COOKIEPATH : '/';
|
||||
$domain = defined('COOKIE_DOMAIN') ? COOKIE_DOMAIN : '';
|
||||
$secure = is_ssl();
|
||||
$http_only = true;
|
||||
$encoded = wp_json_encode($map);
|
||||
if (!is_string($encoded)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID >= 70300) {
|
||||
setcookie($cookie_name, $encoded, array(
|
||||
'expires' => $expire_at,
|
||||
'path' => $path,
|
||||
'domain' => $domain,
|
||||
'secure' => $secure,
|
||||
'httponly' => $http_only,
|
||||
'samesite' => 'Lax',
|
||||
));
|
||||
} else {
|
||||
setcookie($cookie_name, $encoded, $expire_at, $path, $domain, $secure, $http_only);
|
||||
}
|
||||
|
||||
$_COOKIE[$cookie_name] = $encoded;
|
||||
}
|
||||
}
|
||||
|
||||
function itstudio_should_count_post_view($post_id) {
|
||||
$post_id = (int) $post_id;
|
||||
if ($post_id <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (itstudio_is_probably_bot_request()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$window_seconds = (int) apply_filters('itstudio_post_view_window_seconds', 12 * HOUR_IN_SECONDS);
|
||||
$window_seconds = max(60, $window_seconds);
|
||||
$max_entries = (int) apply_filters('itstudio_post_view_cookie_max_entries', 120);
|
||||
$max_entries = max(10, $max_entries);
|
||||
|
||||
$now = time();
|
||||
$key = (string) $post_id;
|
||||
$map = itstudio_read_view_cookie_map();
|
||||
|
||||
foreach ($map as $id => $timestamp) {
|
||||
if (($now - (int) $timestamp) > $window_seconds) {
|
||||
unset($map[$id]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($map[$key]) && ($now - (int) $map[$key]) < $window_seconds) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$map[$key] = $now;
|
||||
if (count($map) > $max_entries) {
|
||||
asort($map, SORT_NUMERIC);
|
||||
$map = array_slice($map, -$max_entries, null, true);
|
||||
}
|
||||
|
||||
itstudio_write_view_cookie_map($map, $window_seconds);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function itstudio_track_post_views() {
|
||||
if (is_admin() || wp_doing_ajax() || wp_doing_cron()) {
|
||||
return;
|
||||
@@ -502,6 +646,10 @@ function itstudio_track_post_views() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!itstudio_should_count_post_view($post_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$views = itstudio_get_post_views($post_id) + 1;
|
||||
update_post_meta($post_id, 'post_views_count', $views);
|
||||
update_post_meta($post_id, 'itstudio_views', $views);
|
||||
|
||||
+113
-83
@@ -1,108 +1,138 @@
|
||||
<?php get_header(); ?>
|
||||
|
||||
<main class="site-main single-post-gh-pro">
|
||||
<div class="container">
|
||||
<main class="site-main single-article-page">
|
||||
<div class="container single-article-shell">
|
||||
<?php while (have_posts()) : the_post(); ?>
|
||||
<?php
|
||||
while (have_posts()) :
|
||||
the_post();
|
||||
?>
|
||||
<!-- 1. 文章头部:极简极客风,去掉 Issue 编号等干扰 -->
|
||||
<header class="gh-pro-header">
|
||||
<div class="gh-pro-meta-top">
|
||||
<?php
|
||||
$categories = get_the_category();
|
||||
if ($categories) :
|
||||
$cat = $categories[0];
|
||||
echo '<a href="' . get_category_link($cat->term_id) . '" class="gh-label-category">' . $cat->name . '</a>';
|
||||
endif;
|
||||
$post_id = get_the_ID();
|
||||
$post_type = get_post_type($post_id);
|
||||
$post_type_object = get_post_type_object($post_type);
|
||||
$post_type_archive_url = get_post_type_archive_link($post_type);
|
||||
$post_type_label_en = $post_type_object ? $post_type_object->labels->name : '';
|
||||
$post_type_label_cn = $post_type_label_en;
|
||||
if ($post_type === 'announcement') {
|
||||
$post_type_label_cn = '公告通知';
|
||||
$post_type_label_en = 'Announcements';
|
||||
} elseif ($post_type === 'news') {
|
||||
$post_type_label_cn = '社团新闻';
|
||||
$post_type_label_en = 'News';
|
||||
} elseif ($post_type === 'post') {
|
||||
$post_type_label_cn = '技术博客';
|
||||
$post_type_label_en = 'Blog';
|
||||
}
|
||||
$views = function_exists('itstudio_get_post_views') ? (int) itstudio_get_post_views($post_id) : 0;
|
||||
|
||||
?>
|
||||
|
||||
<article id="post-<?php the_ID(); ?>" <?php post_class('single-article'); ?>>
|
||||
<header class="single-article-header">
|
||||
<div class="single-article-kicker">
|
||||
<?php if (!empty($post_type_archive_url) && !empty($post_type_label_en)) : ?>
|
||||
<a class="single-article-kicker-link" href="<?php echo esc_url($post_type_archive_url); ?>" data-cn="<?php echo esc_attr($post_type_label_cn); ?>" data-en="<?php echo esc_attr($post_type_label_en); ?>"><?php echo esc_html($post_type_label_en); ?></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<h1 class="entry-title"><?php the_title(); ?></h1>
|
||||
<h1 class="single-article-title"><?php the_title(); ?></h1>
|
||||
|
||||
<div class="gh-pro-meta-bar">
|
||||
<div class="gh-author-lockup">
|
||||
<?php echo get_avatar(get_the_author_meta('ID'), 32); ?>
|
||||
<span class="author-name"><?php the_author(); ?></span>
|
||||
<span class="meta-divider">/</span>
|
||||
<span class="publish-date"><?php echo get_the_date('Y.m.d'); ?></span>
|
||||
</div>
|
||||
|
||||
<div class="gh-stats">
|
||||
<span class="stat-item" title="<?php esc_attr_e('Comments', 'itstudio'); ?>">
|
||||
<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-comment"><path d="M1 2.75C1 1.784 1.784 1 2.75 1h10.5c.966 0 1.75.784 1.75 1.75v7.5A1.75 1.75 0 0 1 13.25 12H9.06l-2.573 2.573A1.458 1.458 0 0 1 4 13.543V12H2.75A1.75 1.75 0 0 1 1 10.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h4.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg>
|
||||
<?php comments_number('0', '1', '%'); ?>
|
||||
<div class="single-article-meta">
|
||||
<span class="single-article-meta-item">
|
||||
<span class="single-article-meta-label" data-cn="发布日期:" data-en="Published: ">Published: </span>
|
||||
<time class="single-article-meta-value" datetime="<?php echo esc_attr(get_the_date('c')); ?>"><?php echo esc_html(get_the_date('Y年m月d日')); ?></time>
|
||||
</span>
|
||||
<span class="single-article-meta-item">
|
||||
<span class="single-article-meta-label" data-cn="作者:" data-en="Author: ">Author: </span>
|
||||
<span class="single-article-meta-value"><?php echo esc_html(get_the_author()); ?></span>
|
||||
</span>
|
||||
<span class="single-article-meta-item">
|
||||
<span class="single-article-meta-label" data-cn="浏览量:" data-en="Views: ">Views: </span>
|
||||
<span class="single-article-meta-value"><?php echo esc_html(number_format_i18n($views)); ?></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- 2. 正文容器:类似 GitHub File/Readme 的框体风格 -->
|
||||
<div class="gh-pro-body-container">
|
||||
<div class="gh-file-box">
|
||||
<div class="gh-file-header">
|
||||
<div class="file-info">
|
||||
<svg aria-hidden="true" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-book"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg>
|
||||
<strong>readme.md</strong>
|
||||
<span class="file-divider"></span>
|
||||
<span class="file-size">
|
||||
<?php
|
||||
$read_time = round(str_word_count(strip_tags(get_the_content())) / 300, 1);
|
||||
printf(
|
||||
'<span data-cn="%s 分钟阅读" data-en="%s mins read"></span>',
|
||||
$read_time,
|
||||
$read_time
|
||||
);
|
||||
?>
|
||||
</span>
|
||||
</div>
|
||||
<div class="file-actions">
|
||||
<a href="#comments" class="btn-sm" data-cn="发表评论" data-en="Post Comment"></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gh-file-content markdown-body">
|
||||
<?php if (has_post_thumbnail()) : ?>
|
||||
<div class="entry-thumbnail-pro">
|
||||
<?php the_post_thumbnail('large'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="single-article-body">
|
||||
<?php the_content(); ?>
|
||||
</div>
|
||||
|
||||
<div class="gh-file-footer">
|
||||
<?php
|
||||
$tags = get_the_tags();
|
||||
if ($tags) :
|
||||
foreach ($tags as $tag) {
|
||||
echo '<span class="gh-tag tag-tag">#' . $tag->name . '</span> ';
|
||||
}
|
||||
endif;
|
||||
$tags = get_the_terms($post_id, 'post_tag');
|
||||
if (!empty($tags) && !is_wp_error($tags)) :
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="single-article-tags">
|
||||
<?php foreach (array_slice($tags, 0, 8) as $tag) : ?>
|
||||
<?php $tag_link = get_term_link($tag); ?>
|
||||
<?php if (!is_wp_error($tag_link)) : ?>
|
||||
<a class="single-article-tag" href="<?php echo esc_url($tag_link); ?>">#<?php echo esc_html($tag->name); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
</footer>
|
||||
<?php endif; ?>
|
||||
</article>
|
||||
|
||||
<!-- 3. 评论区:保持 GitHub Timeline 风格 -->
|
||||
<div class="gh-pro-comments">
|
||||
<section class="single-related">
|
||||
<div class="single-divider" aria-hidden="true"></div>
|
||||
<h2 class="single-related-title" data-cn="相关阅读" data-en="Related Content">Related Content</h2>
|
||||
|
||||
<?php
|
||||
$related_args = array(
|
||||
'post_type' => $post_type,
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => 3,
|
||||
'post__not_in' => array($post_id),
|
||||
'ignore_sticky_posts' => true,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
);
|
||||
$tag_ids = wp_get_post_terms($post_id, 'post_tag', array('fields' => 'ids'));
|
||||
if (!empty($tag_ids) && !is_wp_error($tag_ids)) {
|
||||
$related_args['tax_query'] = array(
|
||||
array(
|
||||
'taxonomy' => 'post_tag',
|
||||
'field' => 'term_id',
|
||||
'terms' => $tag_ids,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$related_query = new WP_Query($related_args);
|
||||
if (!$related_query->have_posts() && isset($related_args['tax_query'])) {
|
||||
unset($related_args['tax_query']);
|
||||
$related_query = new WP_Query($related_args);
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="single-related-grid">
|
||||
<?php if ($related_query->have_posts()) : ?>
|
||||
<?php while ($related_query->have_posts()) : $related_query->the_post(); ?>
|
||||
<?php
|
||||
$related_excerpt = function_exists('itstudio_get_post_excerpt_chars')
|
||||
? itstudio_get_post_excerpt_chars(get_the_ID(), 96)
|
||||
: wp_html_excerpt(wp_strip_all_tags(get_the_excerpt() ?: get_the_content()), 96, '...');
|
||||
?>
|
||||
<article class="single-related-card">
|
||||
<h3 class="single-related-card-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
|
||||
<p class="single-related-card-excerpt"><?php echo esc_html($related_excerpt); ?></p>
|
||||
<a class="single-related-card-link" href="<?php the_permalink(); ?>" data-cn="阅读更多 ->" data-en="Read more ->">Read more -></a>
|
||||
</article>
|
||||
<?php endwhile; ?>
|
||||
<?php wp_reset_postdata(); ?>
|
||||
<?php else : ?>
|
||||
<p class="single-related-empty" data-cn="暂无相关文章" data-en="No related content">No related content</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php if (comments_open() || get_comments_number()) : ?>
|
||||
<section class="single-article-comments gh-pro-comments">
|
||||
<div class="timeline-header">
|
||||
<h3 data-cn="文章讨论" data-en="Discussion"></h3>
|
||||
</div>
|
||||
|
||||
<div class="gh-timeline">
|
||||
<!-- Vertical Line -->
|
||||
<div class="timeline-line"></div>
|
||||
|
||||
<?php
|
||||
// 直接加载评论模板
|
||||
if (comments_open() || get_comments_number()) :
|
||||
comments_template();
|
||||
endif;
|
||||
?>
|
||||
<?php comments_template(); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
<?php endwhile; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
Reference in New Issue
Block a user