进行了一些小修复

This commit is contained in:
2026-08-26 12:10:06 +08:00
parent 90b3ccb006
commit dc14c29878
15 changed files with 11720 additions and 4354 deletions
+1
View File
@@ -7,6 +7,7 @@
/.specs/
/docs/
/tools/*
!/tools/build-public-assets.mjs
/tests/*
!/tools/wp-cli-visual-fixtures.php
!/tests/fixtures/
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+905
View File
@@ -0,0 +1,905 @@
/* source: assets/css/frontend/homepage-fixed/base.css */
/**
* Homepage Fixed Layout — legacy Visual Parity
*
* Implements legacy's homepage visual language:
* - System font stack with Chinese fallbacks
* - 1200px container, 311px sidebar
* - Post cards: list mode (190px thumb) + card mode (3-col grid)
* - legacy shadow/radius/spacing values
* - scale(1.02) thumbnail hover
* - Lazy-load animations (blur/fade/scale)
* - Full responsive: 1200/991/767/640px breakpoints
*/
/* ================================================================
0. ANIMATIONS
================================================================ */
@keyframes aksrt-skeleton-pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
/* ================================================================
1. HOMEPAGE CONTAINER & TYPOGRAPHY
================================================================ */
.aksrt-homepage {
font-family: "Helvetica Neue", Helvetica, Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
font-size: 16px;
line-height: 1.42857143;
color: var(--main-color, #4e5358);
background: transparent;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* Slightly looser than stock legacy short pages: air between stream and footer */
padding-bottom: 28px;
}
.aksrt-homepage a[href] {
transition: color 0.2s, background 0.3s, opacity 0.3s, box-shadow 0.3s, transform 0.3s;
}
.aksrt-homepage .aksrt-skeleton {
animation: aksrt-skeleton-pulse 1.5s ease-in-out infinite;
}
/* ================================================================
2. LAYOUT SHELL
================================================================ */
.aksrt-homepage__fluid-zone.content-shell,
.aksrt-homepage__shell.content-shell {
max-width: min(100%, var(--container, 1200px));
}
.aksrt-homepage__fluid-zone.content-shell {
padding-top: 18px;
padding-bottom: 0;
}
.aksrt-homepage__hero {
width: 100vw;
max-width: 100vw;
margin: 0 calc(-50vw + 50%) 24px;
}
.aksrt-homepage__hero .header-components-container {
margin-bottom: 0;
}
.aksrt-homepage__shell.content-shell {
padding-top: 0;
/* 36px + a bit more breathing room before footer */
padding-bottom: 56px;
}
/* Bottom fluid zone (if any) keeps a little gap above footer */
.aksrt-homepage__fluid-zone--bottom {
margin-bottom: 12px;
}
@media (max-width: 767px) {
.aksrt-homepage {
padding-bottom: 20px;
}
.aksrt-homepage__shell.content-shell {
padding-bottom: 40px;
}
}
/* Dual-column geometry is owned by body.site-layout-* float rules in layout.css. */
.aksrt-homepage__content-layout {
display: block;
gap: 0;
}
@media (max-width: 1200px) {
.aksrt-homepage__fluid-zone.content-shell,
.aksrt-homepage__shell.content-shell {
max-width: 95%;
}
}
.aksrt-homepage__content-zone,
.aksrt-homepage__fluid-zone,
.aksrt-homepage__aside {
display: block;
}
.aksrt-homepage__system-modules {
gap: 0;
padding-bottom: 0;
}
.aksrt-homepage__content-zone.aksrt-homepage__system-modules {
margin-bottom: 20px;
}
.aksrt-homepage__content-zone--featured {
margin-bottom: 20px;
}
.aksrt-homepage__content-zone--operated,
.aksrt-homepage__content-zone--mid,
.aksrt-homepage__content-zone--supplement {
margin-bottom: 20px;
}
.aksrt-homepage__content-zone--supplement {
padding-top: 4px;
}
.aksrt-homepage__content-zone .widget-card:last-child,
.aksrt-homepage__aside .widget:last-child,
.aksrt-homepage__fluid-zone .widget-fluid:last-child {
margin-bottom: 0;
}
/* ================================================================
3. FLUID WIDGETS
================================================================ */
.aksrt-homepage__fluid-zone .widget-fluid {
margin-bottom: 20px;
background: transparent;
padding: 0;
border: 0;
box-shadow: none;
}
.aksrt-homepage .widget-fluid.widget_aksrt_tab_posts,
.aksrt-homepage .widget-fluid.widget_aksrt_category_block,
.aksrt-homepage .widget-fluid.widget_aksrt_category_tabs,
.aksrt-homepage .widget-fluid.widget_aksrt_category_recommend {
padding: 15px;
background: var(--surface-1, #fff);
border: none;
border-radius: var(--main-radius, var(--radius, 8px));
box-shadow: var(--shadow-sm);
}
.aksrt-homepage__content-zone .widget-card,
.aksrt-homepage__aside .widget {
background: var(--surface-1, #fff);
padding: 15px;
border: none;
border-radius: var(--main-radius, var(--radius, 8px));
box-shadow: var(--shadow-sm);
}
/* ================================================================
4. STREAM CONTAINER
================================================================ */
.aksrt-homepage__stream-header {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 12px;
margin-bottom: 10px;
padding: 0;
}
.aksrt-homepage__stream-intro {
min-width: 0;
display: flex;
flex-direction: column;
gap: 4px;
}
.aksrt-homepage__stream-title {
margin: 0;
color: var(--color-ink);
font-size: 20px;
font-weight: 700;
line-height: 1.25;
}
.aksrt-homepage__stream-subtitle {
margin: 0;
color: var(--color-ink-3, #777);
font-size: 13px;
line-height: 1.5;
}
.aksrt-homepage__stream,
.aksrt-homepage__stream.widget-card {
overflow: visible;
padding: 0;
background: transparent;
border: 0;
border-radius: 0;
box-shadow: none;
margin-bottom: 0;
}
/* ================================================================
5. TABS
================================================================ */
.aksrt-homepage__tabs,
.aksrt-homepage__titlebox {
margin-bottom: 6px;
padding-bottom: 0;
border-bottom: 0;
}
.aksrt-homepage__tabs.box-body,
.aksrt-homepage__titlebox.box-body {
padding: 0;
}
.aksrt-homepage__tabs-sentinel {
width: 100%;
height: 1px;
margin: 0;
pointer-events: none;
}
.aksrt-homepage__tabs.home-tab-nav-box {
position: static;
z-index: auto;
background: transparent;
}
.aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"] {
position: sticky;
top: var(--nav-height, 60px);
z-index: 995;
background: transparent;
transition: background-color 0.2s ease,
box-shadow 0.2s ease,
border-radius 0.2s ease,
padding 0.2s ease,
margin 0.2s ease,
backdrop-filter 0.2s ease,
-webkit-backdrop-filter 0.2s ease;
}
.aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-stuck,
.aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-affixed {
margin-bottom: 14px;
padding: 10px 16px;
background: rgba(255, 255, 255, 0.92);
border: none;
border-radius: var(--radius-2xl, 16px);
box-shadow: var(--shadow);
backdrop-filter: saturate(1.6) blur(20px);
-webkit-backdrop-filter: saturate(1.6) blur(20px);
}
.aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-affixed {
position: fixed;
}
html.dark .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-stuck,
html.dark .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-affixed,
html.dark .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-stuck,
html.dark .aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-affixed {
background: rgba(24, 24, 24, 0.82);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.24);
}
.aksrt-homepage__tab-list {
list-style: none;
display: flex;
align-items: center;
gap: 4px;
margin: 0;
padding: 0;
}
.aksrt-homepage__admin-link {
margin-left: auto;
}
.scroll-x {
overflow-x: auto;
overflow-y: hidden;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.aksrt-homepage__tab-item {
display: inline-flex;
flex: 0 0 auto;
padding: 0;
margin: 0;
border-radius: 20px;
font-weight: 500;
transition: background 0.2s ease, color 0.2s ease;
}
.aksrt-homepage__tab-button {
padding: 6px 14px;
border: 0;
background: transparent;
color: var(--color-ink);
font-family: inherit;
font-size: 14px;
font-weight: inherit;
line-height: 1.2;
white-space: nowrap;
border-radius: inherit;
cursor: pointer;
}
.aksrt-homepage__tab-button:hover {
color: var(--color-primary, var(--color-primary));
}
.aksrt-homepage__tab-item.is-active {
background: var(--color-primary, var(--color-primary));
}
.aksrt-homepage__tab-item.is-active .aksrt-homepage__tab-button,
.aksrt-homepage__tab-button[aria-selected="true"] {
color: #fff !important;
}
/* ================================================================
6. SORTBAR + VIEW TOGGLE
================================================================ */
.aksrt-homepage__sortbar {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 10px;
padding: 0 0 8px;
border-bottom: 1px solid var(--color-line, rgba(50, 50, 50, 0.06));
color: var(--color-ink-3, #777);
font-size: 13px;
}
.aksrt-homepage__sortbar-links {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 0;
flex: 1 1 auto;
}
.aksrt-homepage__sortbar-link {
position: relative;
display: inline-flex;
align-items: center;
padding: 0 12px;
color: var(--color-ink-3, #777);
text-decoration: none;
line-height: 1.4;
}
.aksrt-homepage__sortbar-link:first-child {
padding-left: 0;
}
.aksrt-homepage__sortbar-link + .aksrt-homepage__sortbar-link::before {
content: "\00b7";
position: absolute;
left: -2px;
color: var(--color-ink-4, #b1b1b1);
}
.aksrt-homepage__sortbar-link:hover,
.aksrt-homepage__sortbar-link.is-active {
color: var(--color-ink);
}
.aksrt-homepage__view-toggle {
display: inline-flex;
align-items: center;
gap: 6px;
margin-left: auto;
flex: 0 0 auto;
}
.aksrt-homepage__view-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
padding: 0;
border: 0;
background: transparent;
color: var(--color-ink-4, #999);
border-radius: 4px;
cursor: pointer;
transition: color 0.2s, background 0.2s;
}
.aksrt-homepage__view-btn:hover {
color: var(--color-ink);
background: var(--surface-2, #eee);
}
.aksrt-homepage__view-btn.is-active {
color: var(--color-primary);
}
.aksrt-homepage__view-btn svg {
width: 16px;
height: 16px;
fill: currentColor;
}
.title-theme {
position: relative;
padding-left: 1.2em;
font-size: 15px;
font-weight: 700;
line-height: 1.4;
}
.title-theme::before {
position: absolute;
top: 10%;
bottom: 10%;
left: 2px;
width: 4px;
content: "";
background: var(--color-primary);
border-radius: 5px;
box-shadow: 1px 1px 3px -1px var(--color-primary);
}
.aksrt-homepage__page-indicator {
margin-left: 10px;
font-size: 80%;
font-weight: 400;
opacity: 0.7;
}
.aksrt-homepage__panel[hidden],
.index-tab-main .tab-pane[hidden],
.home-tab-content .tab-pane[hidden] {
display: none !important;
}
.aksrt-homepage__panels,
.home-tab-content {
display: block;
}
.aksrt-homepage__panel {
opacity: 0;
transition: opacity 0.3s ease;
}
.aksrt-homepage__panel.is-active,
.aksrt-homepage__panel.active,
.aksrt-homepage__panel.fade.in,
.aksrt-homepage__panel.tab-pane.active,
#index-tab-main.aksrt-homepage__panel,
.home-tab-content .tab-pane.is-active,
.home-tab-content .tab-pane.show,
.home-tab-content .tab-pane.active,
.aksrt-homepage__panel.show {
display: block !important;
visibility: visible !important;
opacity: 1 !important;
}
.home-tab-content .tab-pane.fade.is-active,
.home-tab-content .tab-pane.fade.show,
.home-tab-content .tab-pane.fade.active,
#index-tab-main.fade {
opacity: 1 !important;
}
.aksrt-homepage__panel-contract {
display: none;
}
.flex {
display: flex !important;
}
.flex.xx,
.xx {
flex-direction: column;
}
.flex1,
.flex-1 {
flex: 1 1 auto;
min-width: 0;
}
.jsb,
.jb {
justify-content: space-between;
}
.ac {
align-items: center;
}
/* ================================================================
11. PAGINATION
================================================================ */
.aksrt-homepage__panel-footer {
display: flex;
justify-content: center;
margin-top: 18px;
}
.aksrt-homepage__more,
.aksrt-homepage .aksrt-load-more-btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 34px;
padding: 0 14px;
border: 1px solid var(--color-line, rgba(50, 50, 50, 0.06));
border-radius: var(--radius, 8px);
background: var(--surface-1, #fff);
color: var(--color-ink-3, #777);
font-size: 13px;
font-weight: 500;
transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease;
}
.aksrt-homepage__more:hover,
.aksrt-homepage .aksrt-load-more-btn:hover {
color: var(--color-primary, var(--color-primary));
border-color: var(--color-primary, var(--color-primary));
box-shadow: none;
transform: none;
}
.aksrt-homepage .ajax-pagination {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
margin-top: 20px;
}
.aksrt-homepage .navigation.pagination .nav-links,
.aksrt-homepage .pagination {
gap: 0;
margin: 20px 0 10px;
}
.aksrt-homepage .navigation.pagination .page-numbers,
.aksrt-homepage .pagination .page-numbers {
min-width: 34px;
height: 34px;
padding: 0 10px;
margin: 3px;
border: 1px solid transparent;
border-radius: var(--radius-xs, 3px);
background: var(--surface-4, #eee);
color: var(--color-ink-3, #777);
font-size: 13px;
line-height: 1.4;
}
.aksrt-homepage .navigation.pagination .page-numbers:hover,
.aksrt-homepage .pagination .page-numbers:hover {
opacity: 1;
background: var(--color-primary-soft);
color: var(--color-primary);
}
.aksrt-homepage .navigation.pagination .current,
.aksrt-homepage .pagination .current {
background: var(--color-primary, var(--color-primary)) !important;
color: #fff !important;
}
/* ================================================================
12. SIDEBAR
================================================================ */
.aksrt-homepage__aside > .aksrt-panel,
.aksrt-homepage__aside > .widget {
margin-bottom: 15px;
padding: 15px;
background: var(--surface-1, #fff);
border: 0;
border-radius: var(--main-radius, var(--radius, 8px));
box-shadow: var(--shadow-sm);
}
.aksrt-homepage__aside > .aksrt-panel:last-child,
.aksrt-homepage__aside > .widget:last-child {
margin-bottom: 0;
}
.aksrt-homepage__aside .widget-list li,
.aksrt-homepage__aside .widget_recent_entries li,
.aksrt-homepage__aside .recent-posts-row {
padding-top: 8px;
padding-bottom: 8px;
}
.aksrt-homepage__aside .widget-title,
.aksrt-homepage__content-zone .widget-title {
margin-bottom: 12px;
}
.aksrt-homepage__aside .widget-title {
position: relative;
margin: 0 0 10px;
padding-left: 1.2em;
padding-bottom: 8px;
font-size: 15px;
font-weight: 700;
line-height: 1.4;
}
.aksrt-homepage__aside .widget-title::before {
content: "";
position: absolute;
top: 10%;
bottom: 10%;
left: 2px;
width: 4px;
height: auto;
background: var(--color-primary, var(--color-primary));
border-radius: 5px;
box-shadow: 1px 1px 3px -1px var(--color-primary, var(--color-primary));
transition: transform 0.4s ease;
transform-origin: left;
}
.aksrt-homepage__aside .widget_recent_entries li a,
.aksrt-homepage__aside .widget-list li a {
font-size: 13px;
font-weight: 500;
line-height: 1.5;
}
.aksrt-homepage__aside .widget_recent_entries li {
display: block;
}
.aksrt-homepage__aside .widget_search .search-field {
height: 40px;
border-radius: 30px;
background: var(--surface-2, #eee);
}
.aksrt-homepage__aside .widget_search .search-submit {
top: 4px;
right: 4px;
height: 32px;
padding: 0 12px;
border-radius: 30px;
font-size: 12px;
}
.aksrt-homepage__aside .tag-cloud {
gap: 6px;
}
.aksrt-homepage__aside .tag-cloud a {
padding: 4px 10px;
border-radius: 20px;
font-size: 12px;
border: 0;
background: var(--surface-2, #eee);
transition: background 0.2s, color 0.2s;
}
.aksrt-homepage__aside .tag-cloud a:hover {
background: var(--color-primary, var(--color-primary));
color: #fff;
}
.aksrt-homepage .widget.notop,
.aksrt-homepage .box-body.notop {
padding-top: 0;
}
.aksrt-homepage .widget.nobottom,
.aksrt-homepage .box-body.nobottom {
padding-bottom: 0;
}
.aksrt-homepage .widget.widget_custom_html {
padding: 0;
background: transparent;
box-shadow: none;
border-radius: 0;
}
/* ================================================================
13. LOADING & EMPTY STATES
================================================================ */
.aksrt-homepage .aksrt-loading-indicator {
display: flex;
align-items: center;
gap: 8px;
color: var(--color-ink-3, #777);
font-size: 13px;
}
.aksrt-homepage__stream .no-results {
padding: 32px 16px;
text-align: center;
color: var(--color-ink-4, #999);
}
/* source: assets/css/frontend/homepage-fixed/ajax-tab-skeleton-placeholder.css */
/* AJAX tab skeleton placeholder */
.aksrt-homepage__tab-skeleton {
display: flex;
flex-direction: column;
gap: 15px;
padding: 10px 0;
}
.aksrt-homepage__tab-skeleton-item {
display: flex;
gap: 16px;
padding: 20px;
background: var(--surface-1, #fff);
border: none;
border-radius: var(--main-radius, var(--radius, 8px));
box-shadow: var(--shadow-sm);
animation: aksrt-skeleton-pulse 1.5s ease-in-out infinite;
}
.aksrt-homepage__tab-skeleton-thumb {
width: 190px;
min-width: 190px;
height: 133px;
background: var(--surface-2, #eee);
border-radius: var(--radius, 8px);
}
.aksrt-homepage__tab-skeleton-body {
flex: 1;
display: flex;
flex-direction: column;
gap: 10px;
}
.aksrt-homepage__tab-skeleton-line {
height: 14px;
background: var(--surface-2, #eee);
border-radius: 4px;
}
.aksrt-homepage__tab-skeleton-line:first-child {
width: 70%;
height: 18px;
}
.aksrt-homepage__tab-skeleton-line:nth-child(2) {
width: 100%;
}
.aksrt-homepage__tab-skeleton-line:nth-child(3) {
width: 40%;
}
/* source: assets/css/frontend/homepage-fixed/ajax-tab-error-state.css */
/* AJAX tab error state */
.aksrt-homepage__tab-error {
padding: 32px 16px;
text-align: center;
color: var(--color-ink-4, #999);
font-size: 14px;
background: var(--surface-1);
border: none;
border-radius: var(--main-radius, var(--radius, 8px));
box-shadow: var(--shadow-sm);
}
.aksrt-homepage__tab-retry {
display: inline-flex;
align-items: center;
gap: 6px;
margin-top: 12px;
padding: 8px 16px;
border: 1px solid var(--color-line);
border-radius: var(--radius-btn, 4px);
background: var(--surface-4, #fff);
color: var(--color-ink-3, #777);
font-size: 13px;
cursor: pointer;
transition: color 0.2s, border-color 0.2s, background 0.2s;
}
.aksrt-homepage__tab-retry:hover {
color: var(--color-primary, var(--color-primary));
border-color: var(--color-primary, var(--color-primary));
background: var(--color-primary-soft);
}
/* ================================================================
14. RESPONSIVE — TABLET (max-width: 991px)
================================================================ */
@media (max-width: 991.98px) {
.aksrt-homepage__shell.content-shell,
.aksrt-homepage__fluid-zone.content-shell {
padding-top: 16px;
}
}
/* ================================================================
15. RESPONSIVE — MOBILE (max-width: 767px)
================================================================ */
@media (max-width: 767px) {
.aksrt-homepage__shell.content-shell {
padding-left: 10px;
padding-right: 10px;
}
/* Tab skeleton: smaller thumb */
.aksrt-homepage__tab-skeleton-thumb {
width: 120px;
min-width: 120px;
height: 84px;
}
}
/* ================================================================
16. RESPONSIVE — SMALL MOBILE (max-width: 640px)
================================================================ */
@media (max-width: 640px) {
.aksrt-homepage__stream-header {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.aksrt-homepage__stream-title {
font-size: 20px;
}
.aksrt-homepage__stream-subtitle {
font-size: 13px;
}
.aksrt-homepage__tabs,
.aksrt-homepage__titlebox {
margin-bottom: 8px;
}
.aksrt-homepage__admin-link {
margin-left: 0;
margin-top: 12px;
}
.aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-stuck,
.aksrt-homepage__tabs.home-tab-nav-box[data-sticky-tabs="true"].is-affixed {
padding: 8px 10px;
border-radius: 10px;
}
.aksrt-homepage__sortbar {
gap: 10px;
margin-bottom: 12px;
padding-bottom: 12px;
font-size: 13px;
}
/* Tab skeleton: adapt */
.aksrt-homepage__tab-skeleton-thumb {
width: 96px;
min-width: 96px;
height: 67px;
}
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -146,7 +146,7 @@
* Additive: does NOT alter the AKSRT .btn system above. Lets reused
* legacy-style markup (.but / .badg / .b-* / .jb-* / .c-* / .but-group /
* .but-average / .toggle-radius) render via the --this-* context-coloring vars.
* The --this-* DEFAULTS are set on the base rule here (BEFORE the .b-*/.jb-*
* The --this-* DEFAULTS are set on the base rule here (BEFORE the .b-* and .jb-*
* modifiers) so the cascade resolves colored variants correctly; scoped to
* .but/.badg (never :root) so .float-btn's own var(--this-*, fallback) stays intact.
* Consumes --focus-color-opacity* from compat-vars.css.
File diff suppressed because it is too large Load Diff
+45 -109
View File
@@ -46,47 +46,22 @@ trait ScriptsPart1b {
wp_add_inline_style('aksrt-style', '.lazyloaded{--lazy-animation:lazy_scale!important;}');
}
$core_bundle = get_template_directory() . '/assets/css/build/core.min.css';
if (file_exists($core_bundle)) {
wp_enqueue_style(
'aksrt-core-bundle',
$base_uri . '/assets/css/build/core.min.css',
['aksrt-style'],
filemtime($core_bundle) ?: $version
);
$core_dep = 'aksrt-core-bundle';
} else {
$tokens_path = get_template_directory() . '/assets/css/core/tokens.css';
wp_enqueue_style(
'aksrt-tokens',
$base_uri . '/assets/css/core/tokens.css',
['aksrt-style'],
file_exists($tokens_path) ? (string) filemtime($tokens_path) : $version
);
foreach (['reset', 'typography', 'buttons', 'forms', 'alerts'] as $slug) {
$core_path = get_template_directory() . '/assets/css/core/' . $slug . '.css';
wp_enqueue_style(
'aksrt-core-' . $slug,
$base_uri . '/assets/css/core/' . $slug . '.css',
['aksrt-tokens'],
file_exists($core_path) ? (string) filemtime($core_path) : $version
);
}
$core_dep = 'aksrt-tokens';
}
$core_bundle = get_template_directory() . '/assets/css/build/core.css';
wp_enqueue_style(
'aksrt-core',
$base_uri . '/assets/css/build/core.css',
['aksrt-style'],
file_exists($core_bundle) ? (string) filemtime($core_bundle) : $version
);
$ext_css_files = ['animations', 'components-ext', 'color-utilities'];
foreach ($ext_css_files as $slug) {
$ext_path = get_template_directory() . '/assets/css/core/' . $slug . '.css';
if (file_exists($ext_path)) {
wp_enqueue_style(
'aksrt-ext-' . $slug,
$base_uri . '/assets/css/core/' . $slug . '.css',
[$core_dep],
filemtime($ext_path) ?: $version
);
}
}
$public_bundle = get_template_directory() . '/assets/css/build/public.css';
wp_enqueue_style(
'aksrt-public',
$base_uri . '/assets/css/build/public.css',
['aksrt-core', '_fontawesome'],
file_exists($public_bundle) ? (string) filemtime($public_bundle) : $version
);
$core_dep = 'aksrt-public';
$deps = [$core_dep];
$enqueue_module = function ($slug) use ($base_uri, $version, $deps) {
@@ -99,16 +74,6 @@ trait ScriptsPart1b {
);
};
// AKSRT domain styles load after legacy main.css. The old aggregate is
// intentionally not used because it contains the removed navigation CSS.
$enqueue_module('base');
$enqueue_module('header-userbox');
$enqueue_module('card-primitives');
$enqueue_module('overlay-primitives');
$enqueue_module('layout');
$enqueue_module('footer');
$enqueue_module('floating-buttons');
$enqueue_module('enhancements');
if (!is_user_logged_in() || (bool) get_query_var('aksrt_sign')) {
$auth_css = get_template_directory() . '/assets/css/routes/sign.css';
wp_enqueue_style(
@@ -119,19 +84,6 @@ trait ScriptsPart1b {
);
}
// 4a-b. 全局补充样式(骨架屏、空状态、分页、加载指示器)
foreach (['skeleton', 'empty-state', 'pagination', 'ajax-spinner', 'modal-runtime'] as $slug) {
$css_path = get_template_directory() . '/assets/css/frontend/' . $slug . '.css';
if (file_exists($css_path)) {
wp_enqueue_style(
'aksrt-' . $slug,
$base_uri . '/assets/css/frontend/' . $slug . '.css',
[$core_dep],
filemtime($css_path) ?: $version
);
}
}
// Shared VIP purchase/poll coordinator for modal and credits surfaces.
$vip_on = class_exists('\AKSRT\Settings\Settings')
&& !empty(\AKSRT\Settings\Settings::get_payment_vip_settings()['enabled']);
@@ -152,7 +104,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-vip-coordinator',
$base_uri . '/assets/js/vip-purchase-coordinator.js',
['aksrt-core-request'],
['aksrt-runtime'],
(string) filemtime($vip_coordinator),
true
);
@@ -174,7 +126,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-pay-vip',
$base_uri . '/assets/js/pay-vip.js',
['loader_js', 'aksrt-lazy-image-attr', 'aksrt-core-request', 'aksrt-core-modal-runtime', 'aksrt-vip-coordinator', 'aksrt-notyf'],
['aksrt-runtime', 'aksrt-vip-coordinator'],
(string) filemtime($vip_js),
true
);
@@ -313,7 +265,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-report',
$base_uri . '/assets/js/report.js',
['aksrt-notyf'],
['aksrt-runtime'],
filemtime($report_js_path) ?: $version,
true
);
@@ -327,7 +279,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-author',
$base_uri . '/assets/js/author.js',
['loader_js', 'aksrt-notyf'],
['aksrt-runtime'],
(string) filemtime($author_js_path),
true
);
@@ -415,7 +367,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-order-center',
$base_uri . '/assets/js/order-center.js',
['loader_js', 'aksrt-lazy-image-attr', 'aksrt-rehydrate', 'aksrt-core-request', 'aksrt-core-modal-runtime'],
['aksrt-runtime'],
(string) filemtime($order_center_js),
true
);
@@ -427,14 +379,14 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-route-user-center-auth',
$base_uri . '/assets/js/routes/user-center-auth.js',
['loader_js', 'aksrt-core-request', 'aksrt-core-modal-runtime'],
['aksrt-runtime'],
(string) filemtime($identity_js),
true
);
}
$user_center_deps = file_exists($identity_js)
? ['loader_js', 'aksrt-route-user-center-auth', 'aksrt-notyf']
: ['loader_js', 'aksrt-notyf'];
? ['aksrt-runtime', 'aksrt-route-user-center-auth']
: ['aksrt-runtime'];
if ($has_orders_panel && wp_script_is('aksrt-order-center', 'registered')) {
$user_center_deps[] = 'aksrt-order-center';
}
@@ -455,7 +407,7 @@ trait ScriptsPart1b {
wp_enqueue_style(
'aksrt-route-search',
$base_uri . '/assets/css/routes/search.css',
['aksrt-tokens', 'aksrt-post-card'],
['aksrt-public', 'aksrt-post-card'],
$version
);
}
@@ -465,7 +417,7 @@ trait ScriptsPart1b {
wp_enqueue_style(
'aksrt-route-categories',
$base_uri . '/assets/css/routes/categories.css',
['aksrt-tokens'],
['aksrt-public'],
$version
);
}
@@ -475,7 +427,7 @@ trait ScriptsPart1b {
wp_enqueue_style(
'aksrt-route-friends',
$base_uri . '/assets/css/routes/friends.css',
['aksrt-tokens'],
['aksrt-public'],
file_exists(get_template_directory() . '/assets/css/routes/friends.css')
? (string) filemtime(get_template_directory() . '/assets/css/routes/friends.css')
: $version
@@ -490,7 +442,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-page-navs',
$base_uri . '/assets/js/page-navs.js',
['aksrt-lazy-image-attr'],
['aksrt-runtime'],
(string) filemtime($page_navs_js),
true
);
@@ -501,7 +453,7 @@ trait ScriptsPart1b {
wp_enqueue_style(
'aksrt-route-posts-navs',
$base_uri . '/assets/css/routes/posts-navs.css',
['aksrt-tokens'],
['aksrt-public'],
(string) filemtime($pn_css)
);
}
@@ -520,7 +472,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-posts-navs-page',
$base_uri . '/assets/js/posts-navs-page.js',
['jquery', 'aksrt-notyf'],
['aksrt-runtime'],
(string) filemtime($pn_js),
true
);
@@ -534,7 +486,7 @@ trait ScriptsPart1b {
wp_enqueue_style(
'aksrt-route-archives',
$base_uri . '/assets/css/routes/archives.css',
['aksrt-tokens'],
['aksrt-public'],
(string) filemtime($ar_css)
);
}
@@ -547,7 +499,7 @@ trait ScriptsPart1b {
wp_enqueue_style(
'aksrt-route-ban-appeal',
$base_uri . '/assets/css/routes/ban-appeal.css',
['aksrt-tokens'],
['aksrt-public'],
(string) filemtime($ba_css)
);
}
@@ -556,7 +508,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-ban-appeal-page',
$base_uri . '/assets/js/ban-appeal-page.js',
['aksrt-notyf'],
['aksrt-runtime'],
(string) filemtime($ba_js),
true
);
@@ -570,7 +522,7 @@ trait ScriptsPart1b {
wp_enqueue_style(
'aksrt-messages',
$base_uri . '/assets/css/frontend/messages.css',
['aksrt-tokens'],
['aksrt-public'],
(string) filemtime($messages_css)
);
}
@@ -651,7 +603,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-cms-download',
$base_uri . '/assets/js/cms-download.js',
['loader_js', 'aksrt-runtime', 'aksrt-core-request'],
['aksrt-runtime'],
file_exists($cms_download_js_path) ? (string) filemtime($cms_download_js_path) : $version,
true
);
@@ -659,35 +611,19 @@ trait ScriptsPart1b {
if ($is_fixed_homepage) {
$enqueue_module('post-card');
$homepage_style_deps = ['_main', 'aksrt-layout', 'aksrt-post-card'];
$homepage_style_deps = ['aksrt-public', 'aksrt-post-card'];
$homepage_style_deps = array_values(array_filter(
$homepage_style_deps,
static fn(string $handle): bool => wp_style_is($handle, 'registered')
));
// Enqueue leaf stylesheets directly so each file receives its own cache version.
$homepage_style_parts = [
'base',
'ajax-tab-skeleton-placeholder',
'ajax-tab-error-state',
];
$part_deps = $homepage_style_deps;
foreach ($homepage_style_parts as $part_index => $part_name) {
$is_last_part = $part_index === count($homepage_style_parts) - 1;
$part_handle = $is_last_part
? 'aksrt-homepage-fixed'
: 'aksrt-homepage-fixed-' . sanitize_key($part_name);
$part_relative_path = '/assets/css/frontend/homepage-fixed/' . $part_name . '.css';
$part_path = get_template_directory() . $part_relative_path;
wp_enqueue_style(
$part_handle,
$base_uri . $part_relative_path,
$part_deps,
file_exists($part_path) ? (string) filemtime($part_path) : $version
);
$part_deps = [$part_handle];
}
$homepage_bundle = get_template_directory() . '/assets/css/build/homepage.css';
wp_enqueue_style(
'aksrt-homepage-fixed',
$base_uri . '/assets/css/build/homepage.css',
$homepage_style_deps,
file_exists($homepage_bundle) ? (string) filemtime($homepage_bundle) : $version
);
}
// 积分相关:已登录 + 启用积分功能时全站加载
@@ -700,7 +636,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-credits',
$base_uri . '/assets/js/credits.js',
['loader_js', 'aksrt-lazy-image-attr', 'aksrt-core-request', 'aksrt-core-modal-runtime', 'aksrt-vip-coordinator', 'aksrt-notyf'],
['aksrt-runtime', 'aksrt-vip-coordinator'],
file_exists($credits_js_path) ? (string) filemtime($credits_js_path) : $version,
true
);
@@ -713,7 +649,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-signin',
$base_uri . '/assets/js/signin.js',
['aksrt-core-request', 'aksrt-notyf'],
['aksrt-runtime'],
file_exists($signin_js_path) ? (string) filemtime($signin_js_path) : $version,
true
);
@@ -732,7 +668,7 @@ trait ScriptsPart1b {
wp_enqueue_script(
'aksrt-user-badge-actions',
$base_uri . '/assets/js/user-badge-actions.js',
['loader_js', 'aksrt-core-modal-runtime'],
['aksrt-runtime'],
(string) filemtime($badge_actions_path),
true
);
+44 -202
View File
@@ -20,18 +20,6 @@ trait ScriptsPart1c {
* Fonts / FA / global JS stack / aksrtData (split from enqueue_public).
*/
private function enqueue_public_fonts_js_and_data($base_uri, $core_dep, $deps, $is_fixed_homepage, $is_home_or_archive, $is_single_post, $is_single_resource, $version): void {
$notyf_css = get_template_directory() . '/assets/css/frontend/notyf.css';
wp_enqueue_style(
'aksrt-notyf',
$base_uri . '/assets/css/frontend/notyf.css',
[$core_dep, '_fontawesome'],
file_exists($notyf_css) ? (string) filemtime($notyf_css) : $version
);
// ===== 7. JS =====
$needs_post_list_media = wp_style_is('aksrt-post-card', 'enqueued');
$runtime_uri = $base_uri . '/assets';
$runtime_loader_path = get_template_directory() . '/assets/js/runtime/loader.js';
$runtime_main_path = get_template_directory() . '/assets/js/runtime/main.min.js';
@@ -95,26 +83,15 @@ trait ScriptsPart1c {
]
);
$lazy_image_attr_path = get_template_directory() . '/assets/js/lazy-image-attr.js';
$public_runtime_path = get_template_directory() . '/assets/js/build/public.js';
wp_enqueue_script(
'aksrt-lazy-image-attr',
$base_uri . '/assets/js/lazy-image-attr.js',
'aksrt-runtime',
$base_uri . '/assets/js/build/public.js',
['loader_js'],
file_exists($lazy_image_attr_path) ? (string) filemtime($lazy_image_attr_path) : $version,
file_exists($public_runtime_path) ? (string) filemtime($public_runtime_path) : $version,
true
);
// AKSRT-only modules register after the legacy loader; navigation is owned by main.min.js.
wp_enqueue_script(
'aksrt-rehydrate',
$base_uri . '/assets/js/rehydrate.js',
['loader_js', 'aksrt-lazy-image-attr'],
file_exists(get_template_directory() . '/assets/js/rehydrate.js')
? (string) filemtime(get_template_directory() . '/assets/js/rehydrate.js')
: $version,
true
);
// AJAX 调试(WP_DEBUG 或 ?aksrt_ajax_debug=1):记录所有失败的
// jQuery ajax / fetch 请求,用于定位 vendor main.min.js 的 400 "0" 来源。
if (function_exists('aksrt_ajax_debug_enabled') && aksrt_ajax_debug_enabled()) {
@@ -122,114 +99,19 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-ajax-debug',
$base_uri . '/assets/js/core/ajax-debug.js',
['loader_js'],
['aksrt-runtime'],
file_exists($ajax_debug_path) ? (string) filemtime($ajax_debug_path) : $version,
true
);
}
if ($needs_post_list_media) {
$grade_js = get_template_directory() . '/assets/js/grade.min.js';
wp_enqueue_script(
'aksrt-grade',
$base_uri . '/assets/js/grade.min.js',
[],
file_exists($grade_js) ? (string) filemtime($grade_js) : $version,
true
);
}
$notyf_js = get_template_directory() . '/assets/js/notyf.js';
wp_enqueue_script(
'aksrt-notyf',
$base_uri . '/assets/js/notyf.js',
['jquery'],
file_exists($notyf_js) ? (string) filemtime($notyf_js) : $version,
true
);
// Runtime infrastructure: tbquire / confirm / scrollTopTo / [data-*] declarative
$runtime_js = get_template_directory() . '/assets/js/aksrt-runtime.js';
if (file_exists($runtime_js)) {
wp_enqueue_script(
'aksrt-runtime',
$base_uri . '/assets/js/aksrt-runtime.js',
['aksrt-rehydrate', 'aksrt-notyf'],
(string) filemtime($runtime_js),
true
);
}
// Follow toggle: delegated [data-aksrt-follow] handler; the buttons render on
// user home / user center / single author bar and user cards anywhere.
// Depends on aksrt-runtime because aksrtData (REST root + nonce) is localized
// onto that handle and follow.js reads it at parse time.
$follow_js = get_template_directory() . '/assets/js/follow.js';
if (file_exists($follow_js)) {
wp_enqueue_script(
'aksrt-follow',
$base_uri . '/assets/js/follow.js',
['aksrt-notyf', 'aksrt-runtime'],
(string) filemtime($follow_js),
true
);
}
// Core modules (split from main.js) — register with AksrtFrontend
$core_modules = [
'aksrt-core-article' => 'article.js',
'aksrt-core-comments' => 'comments.js',
'aksrt-core-comment-fixed' => 'comment-fixed-input.js',
'aksrt-core-comment-move' => 'comment-move-form.js',
// Shared legacy-parity list/modal engines (before pagination consumers).
'aksrt-core-ajax-list' => 'ajax-list.js',
'aksrt-core-modal-telemetry' => 'modal-telemetry.js',
'aksrt-core-request' => 'request.js',
'aksrt-core-modal-cache' => 'modal-cache.js',
'aksrt-core-modal-state' => 'modal-state.js',
'aksrt-core-modal-runtime' => 'modal-runtime.js',
'aksrt-core-modal-triggers' => 'modal-triggers.js',
'aksrt-core-pagination' => 'pagination.js',
'aksrt-core-archive' => 'archive.js',
'aksrt-core-footer-tabbar' => 'footer-tabbar.js',
'aksrt-core-misc' => 'misc.js',
];
$core_handles = [];
foreach ($core_modules as $handle => $file) {
$path = get_template_directory() . '/assets/js/core/' . $file;
if (file_exists($path)) {
// Depend on aksrt-runtime so window.aksrtData (localized below) is available.
$deps = ['aksrt-rehydrate', 'aksrt-runtime'];
if ($handle === 'aksrt-core-misc' && $needs_post_list_media) {
$deps[] = 'aksrt-grade';
} elseif ($handle === 'aksrt-core-modal-runtime') {
$deps = array_merge($deps, [
'aksrt-core-modal-telemetry',
'aksrt-core-request',
'aksrt-core-modal-cache',
'aksrt-core-modal-state',
]);
} elseif ($handle === 'aksrt-core-modal-triggers') {
$deps[] = 'aksrt-core-modal-runtime';
}
wp_enqueue_script(
$handle,
$base_uri . '/assets/js/core/' . $file,
$deps,
(string) filemtime($path),
true
);
$core_handles[] = $handle;
}
}
// Code block enhancements (copy button + language label)
$precode_js = get_template_directory() . '/assets/js/precode.js';
if (file_exists($precode_js)) {
if (is_singular() && file_exists($precode_js)) {
wp_enqueue_script(
'aksrt-precode',
$base_uri . '/assets/js/precode.js',
[],
['aksrt-runtime'],
(string) filemtime($precode_js),
true
);
@@ -237,11 +119,15 @@ trait ScriptsPart1c {
// Input field enhancements (auto-resize, counter, validation)
$input_expand_js = get_template_directory() . '/assets/js/input-expand.js';
if (file_exists($input_expand_js)) {
$needs_input_enhancements = is_singular()
|| (bool) get_query_var('aksrt_sign')
|| (bool) get_query_var('aksrt_user_center')
|| (bool) get_query_var('aksrt_author_identifier');
if ($needs_input_enhancements && file_exists($input_expand_js)) {
wp_enqueue_script(
'aksrt-input-expand',
$base_uri . '/assets/js/input-expand.js',
[],
['aksrt-runtime'],
(string) filemtime($input_expand_js),
true
);
@@ -261,11 +147,11 @@ trait ScriptsPart1c {
// Section navs: article TOC / scrollspy
$section_navs_js = get_template_directory() . '/assets/js/section-navs.js';
if (file_exists($section_navs_js)) {
if (is_singular() && file_exists($section_navs_js)) {
wp_enqueue_script(
'aksrt-section-navs',
$base_uri . '/assets/js/section-navs.js',
['aksrt-rehydrate', 'aksrt-runtime'],
['aksrt-runtime'],
(string) filemtime($section_navs_js),
true
);
@@ -273,92 +159,35 @@ trait ScriptsPart1c {
// Video player (MP4/HLS/FLV)
$video_player_js = get_template_directory() . '/assets/js/video-player.js';
if (file_exists($video_player_js)) {
if (is_singular() && file_exists($video_player_js)) {
wp_enqueue_script(
'aksrt-video-player',
$base_uri . '/assets/js/video-player.js',
[],
['aksrt-runtime'],
(string) filemtime($video_player_js),
true
);
}
// Image color extraction
$color_extract_js = get_template_directory() . '/assets/js/color-extract.js';
if (file_exists($color_extract_js)) {
wp_enqueue_script(
'aksrt-color-extract',
$base_uri . '/assets/js/color-extract.js',
[],
(string) filemtime($color_extract_js),
true
);
}
// ===== 全局 UI 增强(骨架屏、悬停动效、灯箱、滚动感知)=====
$enhancements_css = get_template_directory() . '/assets/css/frontend/enhancements.css';
if (file_exists($enhancements_css)) {
wp_enqueue_style(
'aksrt-enhancements',
$base_uri . '/assets/css/frontend/enhancements.css',
[$core_dep],
(string) filemtime($enhancements_css)
);
}
$enhancements_js = get_template_directory() . '/assets/js/enhancements.js';
if (file_exists($enhancements_js)) {
wp_enqueue_script(
'aksrt-enhancements',
$base_uri . '/assets/js/enhancements.js',
['loader_js'],
(string) filemtime($enhancements_js),
true
);
}
$enhancements2_js = get_template_directory() . '/assets/js/enhancements2.js';
if (file_exists($enhancements2_js)) {
wp_enqueue_script(
'aksrt-enhancements2',
$base_uri . '/assets/js/enhancements2.js',
['loader_js'],
(string) filemtime($enhancements2_js),
true
);
}
// Reward (打赏)
$reward_js = get_template_directory() . '/assets/js/reward.js';
if (file_exists($reward_js)) {
if (($is_single_post || $is_single_resource) && file_exists($reward_js)) {
wp_enqueue_script(
'aksrt-reward',
$base_uri . '/assets/js/reward.js',
['loader_js', 'aksrt-core-request'],
['aksrt-runtime'],
(string) filemtime($reward_js),
true
);
}
// Effects (count-up, countdown, marquee, tilt, FPS detection)
$effects_js = get_template_directory() . '/assets/js/effects.js';
if (file_exists($effects_js)) {
wp_enqueue_script(
'aksrt-effects',
$base_uri . '/assets/js/effects.js',
['loader_js'],
(string) filemtime($effects_js),
true
);
}
// Yiyan (一言轮播)
$yiyan_js = get_template_directory() . '/assets/js/yiyan.js';
if (file_exists($yiyan_js)) {
if (($is_single_post || $is_single_resource) && file_exists($yiyan_js)) {
wp_enqueue_script(
'aksrt-yiyan',
$base_uri . '/assets/js/yiyan.js',
[],
['aksrt-runtime'],
(string) filemtime($yiyan_js),
true
);
@@ -366,8 +195,16 @@ trait ScriptsPart1c {
// Frontend translate (默认关)
// Content protection (copy notice / right-click / F12)
$content_protect = class_exists('\AKSRT\Settings\Settings')
? [
'enabled' => (bool) \AKSRT\Settings\Settings::get_value('content_protect_enabled', false),
'copy' => (bool) \AKSRT\Settings\Settings::get_value('content_protect_copy_notice', false),
'right_click' => (bool) \AKSRT\Settings\Settings::get_value('content_protect_right_click', false),
'devtools' => (bool) \AKSRT\Settings\Settings::get_value('content_protect_f12', false),
]
: [];
$content_protect_js = get_template_directory() . '/assets/js/content-protect.js';
if (file_exists($content_protect_js)) {
if (in_array(true, $content_protect, true) && file_exists($content_protect_js)) {
wp_enqueue_script(
'aksrt-content-protect',
$base_uri . '/assets/js/content-protect.js',
@@ -378,8 +215,13 @@ trait ScriptsPart1c {
}
// Site notice popup (global, controlled by Settings)
$site_notice_config = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_system_notice_config()
: [];
$site_notice_enabled = !empty($site_notice_config['enabled'])
&& trim((string) ($site_notice_config['content'] ?? '')) !== '';
$site_notice_css = get_template_directory() . '/assets/css/frontend/site-notice.css';
if (file_exists($site_notice_css)) {
if ($site_notice_enabled && file_exists($site_notice_css)) {
wp_enqueue_style(
'aksrt-site-notice',
$base_uri . '/assets/css/frontend/site-notice.css',
@@ -388,11 +230,11 @@ trait ScriptsPart1c {
);
}
$site_notice_js = get_template_directory() . '/assets/js/site-notice.js';
if (file_exists($site_notice_js)) {
if ($site_notice_enabled && file_exists($site_notice_js)) {
wp_enqueue_script(
'aksrt-site-notice',
$base_uri . '/assets/js/site-notice.js',
[],
['aksrt-runtime'],
(string) filemtime($site_notice_js),
true
);
@@ -400,11 +242,11 @@ trait ScriptsPart1c {
// One state machine owns modal and /sign/ authentication.
$auth_js = get_template_directory() . '/assets/js/auth.js';
if (file_exists($auth_js)) {
if ((!is_user_logged_in() || (bool) get_query_var('aksrt_sign')) && file_exists($auth_js)) {
wp_enqueue_script(
'aksrt-auth',
$base_uri . '/assets/js/auth.js',
['aksrt-notyf', 'aksrt-runtime'],
['aksrt-runtime'],
(string) filemtime($auth_js),
true
);
@@ -415,7 +257,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-homepage-fixed',
$base_uri . '/assets/js/homepage-fixed.js',
['loader_js'],
['aksrt-runtime'],
file_exists($homepage_js_path) ? (string) filemtime($homepage_js_path) : $version,
true
);
@@ -429,7 +271,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-comment-tools',
$base_uri . '/assets/js/comment-tools.js',
['loader_js', 'aksrt-core-comment-fixed', 'aksrt-core-comment-move'],
['aksrt-runtime'],
file_exists($comment_tools_path) ? (string) filemtime($comment_tools_path) : $version,
true
);
@@ -452,7 +294,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-comment-ajax',
$base_uri . '/assets/js/comment-ajax.js',
['loader_js', 'aksrt-core-comments'],
['aksrt-runtime'],
(string) filemtime($comment_ajax_path),
true
);
@@ -465,7 +307,7 @@ trait ScriptsPart1c {
wp_enqueue_script(
'aksrt-page-template',
$base_uri . '/assets/js/page-template.js',
['loader_js'],
['aksrt-runtime'],
(string) filemtime($page_template_path),
true
);
+1 -1
View File
@@ -57,7 +57,7 @@ if (file_exists($js)) {
wp_enqueue_script(
'aksrt-front-submit',
get_template_directory_uri() . '/assets/js/front-submit.js',
['jquery', 'aksrt-notyf'],
['aksrt-runtime'],
(string) filemtime($js),
true
);
@@ -22,7 +22,7 @@ test('modal and sign page use one renderer and one state machine', () => {
assert.match(shared, /data-auth-panel="bind"/);
assert.match(shared, /data-auth-panel="oauth"/);
assert.match(scripts, /assets\/js\/auth\.js/);
assert.match(scripts, /'aksrt-notyf', 'aksrt-runtime'/);
assert.match(scripts, /'aksrt-auth',[\s\S]*?assets\/js\/auth\.js[\s\S]*?\['aksrt-runtime'\]/);
assert.doesNotMatch(scripts, /modal-auth\.js|sign-register\.js/);
assert.doesNotMatch(runtime, /signsubmit-loader|tbquire\(\['sign-register'\]\)|\.on\('click', '\.(?:signin|signup)-loader'/);
assert.doesNotMatch(loader, /sign-register/);
@@ -126,18 +126,20 @@ test('the legacy runtime owns lazySizes while AKSRT consumers share one image-at
const bridge = read('assets/js/lazy-image-attr.js');
const scripts = read('src/Core/ScriptsPart1c.php');
const routeScripts = read('src/Core/ScriptsPart1b.php');
const builder = read('tools/build-public-assets.mjs');
const pagination = read('assets/js/core/pagination.js');
const widgets = read('assets/widgets/frontend.js');
assert.match(runtime, /window\.lazySizes = lazySizes/);
assert.match(bridge, /window\.aksrtGetLazyImageAttr = function/);
assert.match(scripts, /'aksrt-lazy-image-attr'/);
assert.match(scripts, /'aksrt-rehydrate'[\s\S]*?\['loader_js', 'aksrt-lazy-image-attr'\]/);
assert.match(builder, /assets\/js\/lazy-image-attr\.js/);
assert.match(builder, /assets\/js\/rehydrate\.js/);
assert.match(scripts, /assets\/js\/build\/public\.js'[\s\S]*?\['loader_js'\]/);
for (const file of ['pay-vip.js', 'order-center.js', 'page-navs.js', 'credits.js']) {
const blocks = enqueueBlocksFor(routeScripts, file);
assert.ok(blocks.length > 0, `${file} must be enqueued`);
for (const block of blocks) {
assert.match(block, /aksrt-lazy-image-attr/, `${file} must depend on the image-attribute bridge`);
assert.match(block, /aksrt-runtime/, `${file} must depend on the bundled image-attribute bridge`);
}
}
assert.match(runtime, /lazybeforeunveil/);
@@ -277,7 +277,7 @@ test('AJAX pagination can recover, caps auto loading and rehydrates appended med
assert.match(media, /window\.Grade\(container/);
assert.match(media, /linear-gradient\(135deg/);
assert.match(media, /aksrtGradientState/);
assert.match(read('src/Core/ScriptsPart1c.php'), /'aksrt-grade'/);
assert.match(read('tools/build-public-assets.mjs'), /assets\/js\/grade\.min\.js/);
});
test('the pinned visual baseline records all source checksums', () => {
+10 -9
View File
@@ -173,6 +173,7 @@ test('clicking a notification uses the legacy exit class and removal delay', ()
test('notyf CSS and WordPress enqueue match the reference contract', () => {
const css = read('assets/css/frontend/notyf.css');
const scripts = read('src/Core/ScriptsPart1c.php');
const builder = read('tools/build-public-assets.mjs');
assert.match(css, /\.notyn\s*\{[\s\S]*?bottom:\s*6em;[\s\S]*?max-width:\s*320px;[\s\S]*?z-index:\s*10000000;/);
assert.match(css, /\.notyf\s*\{[\s\S]*?position:\s*relative;[\s\S]*?font-size:\s*14px;[\s\S]*?line-height:\s*1\.42857143;[\s\S]*?min-width:\s*200px;[\s\S]*?padding:\s*1em 3em 1em 3\.4em;/);
@@ -188,9 +189,9 @@ test('notyf CSS and WordPress enqueue match the reference contract', () => {
assert.match(css, /content:\s*'\\f057'/);
assert.match(css, /\.notyf\.load::before[\s\S]*?huan-rotate 1s/);
assert.match(scripts, /'aksrt-notyf',[\s\S]*?'\/assets\/js\/notyf\.js',[\s\S]*?\['jquery'\]/);
assert.match(scripts, /'aksrt-runtime',[\s\S]*?\['aksrt-rehydrate', 'aksrt-notyf'\]/);
assert.match(scripts, /'\/assets\/css\/frontend\/notyf\.css',[\s\S]*?'_fontawesome'/);
assert.match(builder, /assets\/js\/notyf\.js/);
assert.match(builder, /assets\/css\/frontend\/notyf\.css/);
assert.match(scripts, /'aksrt-runtime',[\s\S]*?'\/assets\/js\/build\/public\.js',[\s\S]*?\['loader_js'\]/);
});
test('balance center actions use direct fixed-id notyf flows', () => {
@@ -242,8 +243,8 @@ test('balance center actions use direct fixed-id notyf flows', () => {
assert.doesNotMatch(credits, /function initSignin\(|\/signin\/today|POST \/signin/);
assert.match(signinController, /aksrtSigninInitialized/);
assert.match(credits, /aksrtPointsExchangeInitialized[\s\S]*?aksrtWithdrawInitialized/);
assert.match(scripts, /'aksrt-credits',[\s\S]*?\/assets\/js\/credits\.js',[\s\S]*?\[[^\]]*'aksrt-notyf'[^\]]*\]/);
assert.match(scripts, /\$signin_on\s*=\s*is_user_logged_in\(\)[\s\S]*?'aksrt-signin',[\s\S]*?\/assets\/js\/signin\.js',[\s\S]*?'aksrt-core-request'[\s\S]*?'aksrt-notyf'/);
assert.match(scripts, /'aksrt-credits',[\s\S]*?\/assets\/js\/credits\.js',[\s\S]*?\[[^\]]*'aksrt-runtime'[^\]]*\]/);
assert.match(scripts, /\$signin_on\s*=\s*is_user_logged_in\(\)[\s\S]*?'aksrt-signin',[\s\S]*?\/assets\/js\/signin\.js',[\s\S]*?'aksrt-runtime'/);
assert.ok(header.indexOf('data-signin-btn') < header.indexOf('uc-header__message-btn'));
assert.match(header, /uc-header__message-btn[^>]+aria-label="<\?php esc_attr_e\('消息通知'/);
assert.doesNotMatch(header, /<i class="fa fas fa-bell"[^>]*><\/i>\s*<\?php esc_html_e\('消息通知'/);
@@ -282,7 +283,7 @@ test('VIP purchase and points exchange use direct fixed-id notyf flows', () => {
assert.doesNotMatch(vip, /setTip|aksrt-vip-modal-tip/);
assert.doesNotMatch(css, /\.aksrt-vip-modal-tip/);
assert.match(scripts, /'aksrt-pay-vip',[\s\S]*?\/assets\/js\/pay-vip\.js',[\s\S]*?\[[^\]]*'aksrt-notyf'[^\]]*\]/);
assert.match(scripts, /'aksrt-pay-vip',[\s\S]*?\/assets\/js\/pay-vip\.js',[\s\S]*?\[[^\]]*'aksrt-runtime'[^\]]*\]/);
});
test('payment entry points never load the removed legacy pay runtime', () => {
@@ -324,7 +325,7 @@ test('profile save uses AJAX rehydrate and a fixed-id notyf flow without query f
assert.match(profile, /notyf\([^;]+?'success'[^;]+?'aksrt-profile-save-toast'\);/);
assert.match(profile, /notyf\([^;]+?'danger'[^;]+?'aksrt-profile-save-toast'\);/);
assert.match(profile, /fetch\(ajaxUrl, \{ method: 'POST', credentials: 'same-origin', body: data \}\)/);
assert.match(scripts, /\$user_center_deps[\s\S]*?\[[^\]]*'aksrt-notyf'[^\]]*\][\s\S]*?\/assets\/js\/routes\/user-center\.js/);
assert.match(scripts, /\$user_center_deps[\s\S]*?\[[^\]]*'aksrt-runtime'[^\]]*\][\s\S]*?\/assets\/js\/routes\/user-center\.js/);
assert.doesNotMatch(page, /REQUEST_METHOD|profile_error|['"]saved['"]|add_query_arg/);
assert.doesNotMatch([profile, form, layout, lists].join('\n'), /profile-save-msg|profile-form__submit-msg/);
@@ -401,7 +402,7 @@ test('front submit actions use direct fixed-id notyf flows', () => {
assert.match(submit, /needContent[^;]+?'warning'/);
assert.doesNotMatch(submit, /\b(?:window\.)?alert\s*\(/);
assert.match(page, /'aksrt-front-submit',[\s\S]*?'\/assets\/js\/front-submit\.js',[\s\S]*?\[[^\]]*'aksrt-notyf'[^\]]*\]/);
assert.match(page, /'aksrt-front-submit',[\s\S]*?'\/assets\/js\/front-submit\.js',[\s\S]*?\[[^\]]*'aksrt-runtime'[^\]]*\]/);
});
test('legacy frontend toast APIs and selectors are fully removed', () => {
@@ -409,7 +410,7 @@ test('legacy frontend toast APIs and selectors are fully removed', () => {
'assets/js',
'assets/css/frontend',
'assets/css/routes',
'assets/css/build/frontend-base.min.css.disabled',
'assets/css/build',
'page.php',
'templates/pages/page-profile.php',
];
+145
View File
@@ -0,0 +1,145 @@
import { mkdir, readFile, writeFile } from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const cssBuildDir = path.join(repoRoot, 'assets/css/build');
const jsBuildDir = path.join(repoRoot, 'assets/js/build');
const cssBundles = {
'core.css': [
'assets/css/core/tokens.css',
'assets/css/core/reset.css',
'assets/css/core/typography.css',
'assets/css/core/buttons.css',
'assets/css/core/forms.css',
'assets/css/core/alerts.css',
'assets/css/core/animations.css',
'assets/css/core/components-ext.css',
'assets/css/core/color-utilities.css',
],
'public.css': [
'assets/css/frontend/base.css',
'assets/css/frontend/header-userbox.css',
'assets/css/frontend/card-primitives.css',
'assets/css/frontend/overlay-primitives.css',
'assets/css/frontend/layout.css',
'assets/css/frontend/footer.css',
'assets/css/frontend/floating-buttons.css',
'assets/css/frontend/enhancements.css',
'assets/css/frontend/skeleton.css',
'assets/css/frontend/empty-state.css',
'assets/css/frontend/pagination.css',
'assets/css/frontend/ajax-spinner.css',
'assets/css/frontend/modal-runtime.css',
'assets/css/frontend/notyf.css',
],
'homepage.css': [
'assets/css/frontend/homepage-fixed/base.css',
'assets/css/frontend/homepage-fixed/ajax-tab-skeleton-placeholder.css',
'assets/css/frontend/homepage-fixed/ajax-tab-error-state.css',
],
};
const publicScripts = [
'assets/js/lazy-image-attr.js',
'assets/js/rehydrate.js',
'assets/js/notyf.js',
'assets/js/aksrt-runtime.js',
'assets/js/grade.min.js',
'assets/js/core/modal-telemetry.js',
'assets/js/core/request.js',
'assets/js/core/modal-cache.js',
'assets/js/core/modal-state.js',
'assets/js/core/modal-runtime.js',
'assets/js/core/modal-triggers.js',
'assets/js/core/article.js',
'assets/js/core/comments.js',
'assets/js/core/comment-fixed-input.js',
'assets/js/core/comment-move-form.js',
'assets/js/core/ajax-list.js',
'assets/js/core/pagination.js',
'assets/js/core/archive.js',
'assets/js/core/footer-tabbar.js',
'assets/js/core/misc.js',
'assets/js/follow.js',
'assets/js/enhancements.js',
'assets/js/enhancements2.js',
'assets/js/color-extract.js',
'assets/js/effects.js',
];
function normalizePath(filePath) {
return filePath.split(path.sep).join('/');
}
function rewriteCssUrls(css, sourcePath, outputPath) {
const outputDir = path.dirname(outputPath);
return css.replace(/url\(\s*(['"]?)([^)'"\s]+)\1\s*\)/gi, (match, quote, rawUrl) => {
if (/^(?:data:|https?:|\/\/|\/|#|var\()/i.test(rawUrl)) {
return match;
}
const suffixIndex = rawUrl.search(/[?#]/);
const pathname = suffixIndex === -1 ? rawUrl : rawUrl.slice(0, suffixIndex);
const suffix = suffixIndex === -1 ? '' : rawUrl.slice(suffixIndex);
const absoluteAsset = path.resolve(path.dirname(sourcePath), pathname);
let relativeAsset = normalizePath(path.relative(outputDir, absoluteAsset));
if (!relativeAsset.startsWith('.')) {
relativeAsset = `./${relativeAsset}`;
}
const wrapper = quote || '"';
return `url(${wrapper}${relativeAsset}${suffix}${wrapper})`;
});
}
async function expandCss(sourcePath, outputPath, stack = []) {
const absoluteSource = path.resolve(sourcePath);
if (stack.includes(absoluteSource)) {
throw new Error(`Circular CSS import: ${normalizePath(path.relative(repoRoot, absoluteSource))}`);
}
const source = await readFile(absoluteSource, 'utf8');
const importPattern = /@import\s+(?:url\(\s*)?['"]([^'"]+\.css)['"]\s*\)?\s*;/gi;
let expanded = '';
let cursor = 0;
let match;
while ((match = importPattern.exec(source)) !== null) {
expanded += rewriteCssUrls(source.slice(cursor, match.index), absoluteSource, outputPath);
const importedPath = path.resolve(path.dirname(absoluteSource), match[1]);
expanded += await expandCss(importedPath, outputPath, [...stack, absoluteSource]);
cursor = importPattern.lastIndex;
}
expanded += rewriteCssUrls(source.slice(cursor), absoluteSource, outputPath);
return expanded.trimEnd();
}
async function buildCssBundle(outputName, sources) {
const outputPath = path.join(cssBuildDir, outputName);
const sections = [];
for (const source of sources) {
const sourcePath = path.join(repoRoot, source);
sections.push(`/* source: ${source} */\n${await expandCss(sourcePath, outputPath)}`);
}
await writeFile(outputPath, `${sections.join('\n\n')}\n`, 'utf8');
}
async function buildScriptBundle() {
const sections = [];
for (const source of publicScripts) {
const content = (await readFile(path.join(repoRoot, source), 'utf8')).trimEnd();
sections.push(`/* source: ${source} */\n${content}\n;`);
}
await writeFile(path.join(jsBuildDir, 'public.js'), `${sections.join('\n\n')}\n`, 'utf8');
}
await mkdir(cssBuildDir, { recursive: true });
await mkdir(jsBuildDir, { recursive: true });
for (const [outputName, sources] of Object.entries(cssBundles)) {
await buildCssBundle(outputName, sources);
}
await buildScriptBundle();
console.log('Built public CSS and JS bundles.');