Добавлены новые разделы документации: "Города и регистрация", "Крафты", "Приват и защита", "SkinRestore". Каждый раздел содержит информацию о статусе, что будет добавлено, и полезные советы для пользователей.
This commit is contained in:
@@ -3,7 +3,6 @@ import config from 'virtual:starlight/user-config';
|
||||
|
||||
import LanguageSelect from 'virtual:starlight/components/LanguageSelect';
|
||||
import Search from 'virtual:starlight/components/Search';
|
||||
import SiteTitle from 'virtual:starlight/components/SiteTitle';
|
||||
import SocialIcons from 'virtual:starlight/components/SocialIcons';
|
||||
|
||||
const shouldRenderSearch =
|
||||
@@ -21,7 +20,15 @@ const topLinks = [
|
||||
<div class="wiki-header-shell">
|
||||
<div class="header wiki-header">
|
||||
<div class="title-wrapper sl-flex">
|
||||
<SiteTitle />
|
||||
<a class="wiki-brand" href="/" aria-label="PARABOX PROJECT">
|
||||
<span class="wiki-brand__icon" aria-hidden="true">
|
||||
<img src="/brand-logo.png" alt="" loading="eager" decoding="async" />
|
||||
</span>
|
||||
<span class="wiki-brand__copy">
|
||||
<span class="wiki-brand__title">PARABOX</span>
|
||||
<span class="wiki-brand__subtitle">PROJECT</span>
|
||||
</span>
|
||||
</a>
|
||||
<nav class="wiki-top-nav" aria-label="Быстрая навигация">
|
||||
{
|
||||
topLinks.map((link) => (
|
||||
@@ -89,10 +96,148 @@ const topLinks = [
|
||||
</div>
|
||||
|
||||
<button class="wiki-back-to-top" type="button" aria-label="Прокрутить в начало" data-back-to-top>
|
||||
<span aria-hidden="true">↑</span>
|
||||
<svg aria-hidden="true" class="wiki-back-to-top__icon" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M12 18V6" />
|
||||
<path d="m6.8 11.2 5.2-5.2 5.2 5.2" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<script>
|
||||
const emojiPattern = (() => {
|
||||
try {
|
||||
return new RegExp('[\\p{Extended_Pictographic}\\u2600-\\u27BF]', 'gu');
|
||||
} catch {
|
||||
return /[\u2600-\u27BF]/g;
|
||||
}
|
||||
})();
|
||||
|
||||
const stripDecorativeSymbols = (value) =>
|
||||
value
|
||||
.replace(emojiPattern, '')
|
||||
.replace(/\s{2,}/g, ' ')
|
||||
.trim();
|
||||
|
||||
const normalizeLabelKey = (value) => stripDecorativeSymbols(value).toLowerCase();
|
||||
|
||||
const minimalIconByHeading = new Map([
|
||||
['настройки', '/icons/minimal-solid/gear.png'],
|
||||
['личные сообщения', '/icons/minimal-solid/message.png'],
|
||||
['игнор', '/icons/minimal-solid/safe.png'],
|
||||
['развлечения', '/icons/minimal-solid/game-controller.png'],
|
||||
['rp и взаимодействие', '/icons/minimal-solid/community.png'],
|
||||
['статус игрока', '/icons/minimal-solid/user-profile.png'],
|
||||
['информация', '/icons/minimal-solid/exclamation.png'],
|
||||
['символы', '/icons/minimal-solid/keyboard.png']
|
||||
]);
|
||||
|
||||
const sanitizeNavLabels = () => {
|
||||
const navLinks = document.querySelectorAll('.sidebar-content a, starlight-toc a, mobile-starlight-toc a');
|
||||
|
||||
navLinks.forEach((linkNode) => {
|
||||
if (!(linkNode instanceof HTMLElement)) return;
|
||||
|
||||
const sourceText = linkNode.textContent;
|
||||
if (!sourceText) return;
|
||||
|
||||
const normalizedText = stripDecorativeSymbols(sourceText);
|
||||
|
||||
if (!normalizedText || normalizedText === sourceText.trim()) return;
|
||||
linkNode.textContent = normalizedText;
|
||||
});
|
||||
};
|
||||
|
||||
const sanitizeDocHeadings = () => {
|
||||
const headings = document.querySelectorAll('.sl-markdown-content :is(h1, h2, h3, h4, h5, h6)');
|
||||
|
||||
headings.forEach((headingNode) => {
|
||||
if (!(headingNode instanceof HTMLElement)) return;
|
||||
|
||||
const sourceText = headingNode.textContent;
|
||||
if (!sourceText) return;
|
||||
|
||||
const normalizedText = stripDecorativeSymbols(sourceText);
|
||||
|
||||
if (!normalizedText || normalizedText === sourceText.trim()) return;
|
||||
headingNode.textContent = normalizedText;
|
||||
});
|
||||
};
|
||||
|
||||
const decorateSectionIcons = () => {
|
||||
const headings = document.querySelectorAll('.sl-markdown-content h3');
|
||||
|
||||
headings.forEach((headingNode) => {
|
||||
if (!(headingNode instanceof HTMLElement)) return;
|
||||
|
||||
const sourceText = headingNode.textContent;
|
||||
if (!sourceText) return;
|
||||
|
||||
const normalizedText = normalizeLabelKey(sourceText);
|
||||
const iconPath = minimalIconByHeading.get(normalizedText);
|
||||
if (!iconPath) return;
|
||||
|
||||
if (headingNode.querySelector('.minimal-heading-icon')) return;
|
||||
|
||||
const iconNode = document.createElement('span');
|
||||
iconNode.className = 'minimal-heading-icon';
|
||||
iconNode.setAttribute('aria-hidden', 'true');
|
||||
iconNode.style.setProperty('--icon-url', `url('${iconPath}')`);
|
||||
headingNode.prepend(iconNode);
|
||||
});
|
||||
};
|
||||
|
||||
const copyTextToClipboard = async (value) => {
|
||||
if (navigator.clipboard?.writeText) {
|
||||
await navigator.clipboard.writeText(value);
|
||||
return;
|
||||
}
|
||||
|
||||
const helperInput = document.createElement('textarea');
|
||||
helperInput.value = value;
|
||||
helperInput.setAttribute('readonly', '');
|
||||
helperInput.style.position = 'fixed';
|
||||
helperInput.style.opacity = '0';
|
||||
document.body.appendChild(helperInput);
|
||||
helperInput.select();
|
||||
document.execCommand('copy');
|
||||
helperInput.remove();
|
||||
};
|
||||
|
||||
const bindCopyIpChips = () => {
|
||||
const copyButtons = document.querySelectorAll('[data-copy-ip]');
|
||||
|
||||
copyButtons.forEach((buttonNode) => {
|
||||
if (!(buttonNode instanceof HTMLButtonElement)) return;
|
||||
if (buttonNode.dataset.copyBound === 'true') return;
|
||||
|
||||
buttonNode.dataset.copyBound = 'true';
|
||||
buttonNode.classList.add('is-copy-ready');
|
||||
if (!buttonNode.title) {
|
||||
buttonNode.title = 'Нажмите, чтобы скопировать';
|
||||
}
|
||||
buttonNode.addEventListener('click', async () => {
|
||||
const value = buttonNode.dataset.copyIp?.trim();
|
||||
if (!value) return;
|
||||
|
||||
try {
|
||||
await copyTextToClipboard(value);
|
||||
buttonNode.classList.add('is-copied');
|
||||
buttonNode.setAttribute('aria-label', `Скопировано: ${value}`);
|
||||
window.setTimeout(() => {
|
||||
buttonNode.classList.remove('is-copied');
|
||||
buttonNode.setAttribute('aria-label', `Скопировать: ${value}`);
|
||||
}, 1200);
|
||||
} catch {
|
||||
buttonNode.classList.add('is-copy-error');
|
||||
buttonNode.setAttribute('aria-label', `Не удалось скопировать: ${value}`);
|
||||
window.setTimeout(() => {
|
||||
buttonNode.classList.remove('is-copy-error');
|
||||
buttonNode.setAttribute('aria-label', `Скопировать: ${value}`);
|
||||
}, 1400);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const enhanceSidebarGroupLinks = () => {
|
||||
const targets = [{ label: 'Алкоголь', href: '/alcohol/' }];
|
||||
const labelNodes = document.querySelectorAll('.sidebar-content details > summary .group-label .large');
|
||||
@@ -164,6 +309,10 @@ const topLinks = [
|
||||
});
|
||||
|
||||
enhanceSidebarGroupLinks();
|
||||
sanitizeNavLabels();
|
||||
sanitizeDocHeadings();
|
||||
decorateSectionIcons();
|
||||
bindCopyIpChips();
|
||||
setReadProgress();
|
||||
window.addEventListener('scroll', setReadProgress, { passive: true });
|
||||
window.addEventListener('resize', setReadProgress);
|
||||
@@ -177,6 +326,10 @@ const topLinks = [
|
||||
|
||||
document.addEventListener('astro:page-load', () => {
|
||||
enhanceSidebarGroupLinks();
|
||||
sanitizeNavLabels();
|
||||
sanitizeDocHeadings();
|
||||
decorateSectionIcons();
|
||||
bindCopyIpChips();
|
||||
setReadProgress();
|
||||
});
|
||||
</script>
|
||||
@@ -203,10 +356,70 @@ const topLinks = [
|
||||
padding: 0.25rem;
|
||||
margin: -0.25rem;
|
||||
min-width: 0;
|
||||
gap: 1rem;
|
||||
gap: 1.1rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.wiki-brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.55rem;
|
||||
text-decoration: none;
|
||||
flex-shrink: 0;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0.3rem;
|
||||
padding: 0.2rem 0.28rem 0.2rem 0.22rem;
|
||||
transition: border-color 150ms ease, background 150ms ease;
|
||||
}
|
||||
|
||||
.wiki-brand:hover {
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 32%, transparent);
|
||||
background: color-mix(in srgb, var(--sl-color-accent-low) 64%, transparent);
|
||||
}
|
||||
|
||||
.wiki-brand__icon {
|
||||
width: 1.85rem;
|
||||
height: 1.85rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.wiki-brand__icon img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
border-radius: 0;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.wiki-brand__copy {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.wiki-brand__title {
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-size: 1.43rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.02em;
|
||||
color: var(--sl-color-white);
|
||||
}
|
||||
|
||||
.wiki-brand__subtitle {
|
||||
margin-top: 0.14rem;
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-size: 0.56rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.28em;
|
||||
color: var(--sl-color-gray-3);
|
||||
}
|
||||
|
||||
.wiki-top-nav {
|
||||
display: none;
|
||||
gap: 0.45rem;
|
||||
@@ -327,51 +540,56 @@ const topLinks = [
|
||||
.wiki-back-to-top {
|
||||
position: fixed;
|
||||
top: auto;
|
||||
right: max(0.75rem, env(safe-area-inset-right));
|
||||
bottom: max(1.1rem, env(safe-area-inset-bottom));
|
||||
right: max(1.35rem, calc(env(safe-area-inset-right) + 0.8rem));
|
||||
bottom: max(1.45rem, calc(env(safe-area-inset-bottom) + 0.7rem));
|
||||
z-index: 30;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 70%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 74%, transparent);
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(
|
||||
140deg,
|
||||
color-mix(in srgb, var(--wiki-purple-2) 78%, #101522),
|
||||
color-mix(in srgb, var(--wiki-blue-2) 82%, #101522)
|
||||
color-mix(in srgb, var(--wiki-purple-2) 74%, #101522),
|
||||
color-mix(in srgb, var(--wiki-blue-2) 84%, #101522)
|
||||
);
|
||||
color: #f6f9ff;
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.01em;
|
||||
width: 2.6rem;
|
||||
height: 2.6rem;
|
||||
width: 3.1rem;
|
||||
height: 3.1rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
box-shadow:
|
||||
0 10px 24px hsl(220 95% 62% / 0.24),
|
||||
0 0 0 1px hsl(214 88% 70% / 0.22);
|
||||
0 0 0 1px hsl(214 88% 70% / 0.24),
|
||||
0 0 24px hsl(217 100% 68% / 0.38),
|
||||
0 0 42px hsl(221 100% 65% / 0.22);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(6px);
|
||||
transform: translateY(8px) scale(0.96);
|
||||
pointer-events: none;
|
||||
transition: opacity 160ms ease, transform 160ms ease, border-color 160ms ease;
|
||||
transition: opacity 180ms ease, transform 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
|
||||
}
|
||||
|
||||
.wiki-back-to-top__icon {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
stroke: currentColor;
|
||||
stroke-width: 2.15;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.wiki-back-to-top.is-visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(1);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.wiki-back-to-top:hover {
|
||||
border-color: color-mix(in srgb, #9ec4ff 80%, transparent);
|
||||
box-shadow:
|
||||
0 14px 28px hsl(220 95% 62% / 0.32),
|
||||
0 0 0 1px hsl(214 88% 70% / 0.35),
|
||||
0 0 18px hsl(220 96% 68% / 0.34);
|
||||
0 0 28px hsl(219 97% 70% / 0.44),
|
||||
0 0 50px hsl(221 98% 68% / 0.27);
|
||||
}
|
||||
|
||||
.social-icons::after {
|
||||
@@ -415,12 +633,36 @@ const topLinks = [
|
||||
}
|
||||
|
||||
@media (max-width: 50rem) {
|
||||
.wiki-brand {
|
||||
padding: 0.14rem 0.2rem;
|
||||
gap: 0.42rem;
|
||||
}
|
||||
|
||||
.wiki-brand__icon {
|
||||
width: 1.55rem;
|
||||
height: 1.55rem;
|
||||
}
|
||||
|
||||
.wiki-brand__title {
|
||||
font-size: 1.08rem;
|
||||
}
|
||||
|
||||
.wiki-brand__subtitle {
|
||||
font-size: 0.46rem;
|
||||
letter-spacing: 0.24em;
|
||||
}
|
||||
|
||||
.wiki-back-to-top {
|
||||
top: auto;
|
||||
right: max(0.62rem, env(safe-area-inset-right));
|
||||
bottom: max(1rem, env(safe-area-inset-bottom));
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
right: max(1rem, calc(env(safe-area-inset-right) + 0.52rem));
|
||||
bottom: max(1.18rem, calc(env(safe-area-inset-bottom) + 0.58rem));
|
||||
width: 2.85rem;
|
||||
height: 2.85rem;
|
||||
}
|
||||
|
||||
.wiki-back-to-top__icon {
|
||||
width: 1.34rem;
|
||||
height: 1.34rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user