feat: add toc with accordion animation, add optional toc toggle, lower heti css priority

This commit is contained in:
radishzzz 2025-03-28 00:26:32 +00:00
parent ab74c0abdf
commit dc17f304c1
22 changed files with 280 additions and 167 deletions

View file

@ -30,7 +30,6 @@
"rehype-katex": "^7.0.1",
"rehype-slug": "^6.0.0",
"remark-math": "^6.0.0",
"remark-toc": "^9.0.0",
"sanitize-html": "^2.15.0"
},
"devDependencies": {

37
pnpm-lock.yaml generated
View file

@ -59,9 +59,6 @@ importers:
remark-math:
specifier: ^6.0.0
version: 6.0.0
remark-toc:
specifier: ^9.0.0
version: 9.0.0
sanitize-html:
specifier: ^2.15.0
version: 2.15.0
@ -925,9 +922,6 @@ packages:
'@types/sax@1.2.7':
resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==}
'@types/ungap__structured-clone@1.2.0':
resolution: {integrity: sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA==}
'@types/unist@2.0.11':
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
@ -1691,8 +1685,8 @@ packages:
duplexer@0.1.2:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
electron-to-chromium@1.5.126:
resolution: {integrity: sha512-AtH1uLcTC72LA4vfYcEJJkrMk/MY/X0ub8Hv7QGAePW2JkeUFHEL/QfS4J77R6M87Sss8O0OcqReSaN1bpyA+Q==}
electron-to-chromium@1.5.127:
resolution: {integrity: sha512-Ke5OggqOtEqzCzcUyV+9jgO6L6sv1gQVKGtSExXHjD/FK0p4qzPZbrDsrCdy0DptcQprD0V80RCBYSWLMhTTgQ==}
emmet@2.4.11:
resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==}
@ -2553,9 +2547,6 @@ packages:
mdast-util-to-string@4.0.0:
resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
mdast-util-toc@7.1.0:
resolution: {integrity: sha512-2TVKotOQzqdY7THOdn2gGzS9d1Sdd66bvxUyw3aNpWfcPXCLYSJCCgfPy30sEtuzkDraJgqF35dzgmz6xlvH/w==}
mdn-data@2.0.28:
resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==}
@ -3071,9 +3062,6 @@ packages:
remark-stringify@11.0.0:
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
remark-toc@9.0.0:
resolution: {integrity: sha512-KJ9txbo33GjDAV1baHFze7ij4G8c7SGYoY8Kzsm2gzFpbhL/bSoVpMMzGa3vrNDSWASNd/3ppAqL7cP2zD6JIA==}
request-light@0.5.8:
resolution: {integrity: sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==}
@ -4610,8 +4598,6 @@ snapshots:
dependencies:
'@types/node': 22.13.14
'@types/ungap__structured-clone@1.2.0': {}
'@types/unist@2.0.11': {}
'@types/unist@3.0.3': {}
@ -5330,7 +5316,7 @@ snapshots:
browserslist@4.24.4:
dependencies:
caniuse-lite: 1.0.30001707
electron-to-chromium: 1.5.126
electron-to-chromium: 1.5.127
node-releases: 2.0.19
update-browserslist-db: 1.1.3(browserslist@4.24.4)
@ -5589,7 +5575,7 @@ snapshots:
duplexer@0.1.2: {}
electron-to-chromium@1.5.126: {}
electron-to-chromium@1.5.127: {}
emmet@2.4.11:
dependencies:
@ -6754,16 +6740,6 @@ snapshots:
dependencies:
'@types/mdast': 4.0.4
mdast-util-toc@7.1.0:
dependencies:
'@types/mdast': 4.0.4
'@types/ungap__structured-clone': 1.2.0
'@ungap/structured-clone': 1.3.0
github-slugger: 2.0.0
mdast-util-to-string: 4.0.0
unist-util-is: 6.0.0
unist-util-visit: 5.0.0
mdn-data@2.0.28: {}
mdn-data@2.0.30: {}
@ -7518,11 +7494,6 @@ snapshots:
mdast-util-to-markdown: 2.1.2
unified: 11.0.5
remark-toc@9.0.0:
dependencies:
'@types/mdast': 4.0.4
mdast-util-toc: 7.1.0
request-light@0.5.8: {}
request-light@0.7.0: {}

View file

@ -33,6 +33,7 @@ const navItems = [
---
<nav
aria-label="Site Navigation"
class:list={[
isPost ? 'hidden lg:block' : '',
'mb-10.5 text-3.6 font-semibold leading-8.75 font-navbar',

View file

@ -2,6 +2,7 @@
import { OverlayScrollbars } from 'overlayscrollbars'
function setupScrollbar() {
// Add scrollbar to body
const bodyElement = document.body
if (!bodyElement.hasAttribute('data-scrollbar-initialized')) {
OverlayScrollbars({
@ -20,6 +21,7 @@ function setupScrollbar() {
bodyElement.setAttribute('data-scrollbar-initialized', 'true')
}
// Add scrollbar to code blocks
const preElements = document.querySelectorAll('pre')
preElements.forEach((pre) => {
if (!pre.hasAttribute('data-scrollbar-initialized')) {
@ -30,7 +32,7 @@ function setupScrollbar() {
},
}, {
scrollbars: {
theme: 'scrollbar-code',
theme: 'scrollbar-widget',
autoHide: 'leave',
autoHideDelay: 500,
},
@ -39,6 +41,25 @@ function setupScrollbar() {
pre.setAttribute('data-scrollbar-initialized', 'true')
}
})
// Add scrollbar to TOC content
const tocElement = document.getElementById('toc-content')
if (tocElement && !tocElement.hasAttribute('data-scrollbar-initialized')) {
OverlayScrollbars({
target: tocElement,
cancel: {
nativeScrollbarsOverlaid: true,
},
}, {
scrollbars: {
theme: 'scrollbar-widget',
autoHide: 'leave',
autoHideDelay: 500,
},
})
tocElement.setAttribute('data-scrollbar-initialized', 'true')
}
}
setupScrollbar()
@ -64,7 +85,7 @@ document.addEventListener('astro:after-swap', setupScrollbar)
--os-handle-min-size: 12%;
}
.scrollbar-code {
.scrollbar-widget {
--os-size: 0.6rem;
--os-padding-perpendicular: 0.1rem;
--os-padding-axis: 0.2rem;
@ -80,7 +101,7 @@ document.addEventListener('astro:after-swap', setupScrollbar)
}
@media (max-width: 1023px) {
.os-scrollbar {
.os-scrollbar.scrollbar-body {
display: none !important;
}
}

View file

@ -0,0 +1,112 @@
---
import type { MarkdownHeading } from 'astro'
import { ui } from '@/i18n/ui'
import { getPageInfo } from '@/utils/page'
interface Props {
headings: MarkdownHeading[]
}
const { currentLang } = getPageInfo(Astro.url.pathname)
const currentUI = ui[currentLang as keyof typeof ui]
const { headings = [] } = Astro.props
const filteredHeadings = headings.filter(heading =>
heading.depth >= 2
&& heading.depth <= 4
&& heading.text !== 'Footnotes',
)
---
{filteredHeadings.length > 0 && (
<div
class="relative mb-6 bg-secondary/5"
border="~ secondary/5 rounded solid"
transition="~ duration-300 ease-in-out"
>
{/* Accordion toggle for expandable TOC */}
<input
type="checkbox"
id="toc-toggle"
class="accordion-toggle"
hidden
/>
<label
for="toc-toggle"
class="absolute inset-0 z-99 cursor-pointer"
></label>
{/* TOC title bar */}
<div class="h-12 w-full flex items-center bg-secondary/0">
<span class="toc-title">
{currentUI.toc}
</span>
</div>
{/* Expandable content wrapper */}
<div class="accordion-wrapper">
<nav
id="toc-content"
class="accordion-content"
aria-label="Table of Contents"
>
<ul class="toc-list">
{filteredHeadings.map(heading => (
<li
class:list={{
'ml-0': heading.depth === 2,
'ml-4': heading.depth === 3,
'ml-8': heading.depth === 4,
}}
>
<a
href={`#${heading.slug}`}
class:list={[
{ 'toc-link-h2': heading.depth === 2 },
{ 'toc-link-h3': heading.depth === 3 },
{ 'toc-link-h4': heading.depth === 4 },
]}
>
{heading.text}
</a>
</li>
))}
</ul>
</nav>
</div>
</div>
)}
<!-- Override heti default styles -->
<style>
.toc-title {
--at-apply: 'font-semibold pl-4 px-4 py-3';
}
.toc-list {
--at-apply: 'list-none pl-0 space-y-2 mt-1 mb-4';
}
.toc-link-h2 {
--at-apply: 'text-sm no-underline font-semibold';
}
.toc-link-h3 {
--at-apply: 'text-sm no-underline font-normal';
}
.toc-link-h4 {
--at-apply: 'text-sm no-underline font-normal';
}
/* Initial collapsed state with zero height grid row */
.accordion-wrapper {
--at-apply: 'grid rows-[0fr] duration-300 ease-in-out';
}
.accordion-content {
--at-apply: 'overflow-hidden max-h-66 lg:max-h-82 z-99 pl-4';
}
/* When toggle is checked, expand the wrapper to show content */
.accordion-toggle:checked ~ .accordion-wrapper {
grid-template-rows: 1fr;
}
.accordion-toggle:checked ~ .accordion-wrapper .accordion-content {
--at-apply: 'overflow-y-auto';
}
</style>

View file

@ -14,7 +14,7 @@ const postsCollection = defineCollection({
// Advanced
draft: z.boolean().optional().default(false),
pin: z.number().int().min(0).max(99).optional().default(0),
toc: z.boolean().optional().default(false),
toc: z.boolean().optional().default(true),
lang: z.enum(['', ...allLocales]).optional().default(''),
abbrlink: z.string().optional().default('').refine(
abbrlink => !abbrlink || /^[a-z0-9\-]*$/.test(abbrlink),

View file

@ -231,7 +231,7 @@ Pins the article to the top. The higher the number, the higher the priority of t
#### toc
Enables the table of contents. This feature is not yet implemented.
Generate table of contents. Set to false to disable automatic generation. Default is true.
#### lang
@ -243,15 +243,15 @@ Specifies the article language. Only one language can be specified. If not speci
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/banana.md -> example.com/es/posts/banana/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/orange.md -> example.com/ru/posts/orange/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink

View file

@ -231,7 +231,7 @@ Fija el artículo en la parte superior. Cuanto mayor sea el número, mayor será
#### toc
Habilita la tabla de contenidos. Esta función aún no está implementada.
¿Generar índice? Si se establece en false, se desactiva la generación automática. Valor predeterminado: true.
#### lang
@ -243,15 +243,15 @@ Especifica el idioma del artículo. Solo se puede especificar un idioma. Si no s
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/banana.md -> example.com/es/posts/banana/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/orange.md -> example.com/ru/posts/orange/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink

View file

@ -231,7 +231,7 @@ abbrlink: theme-guide
#### toc
目次を有効にします。この機能はまだ実装されていません
目次を自動生成するかどうか。false に設定すると自動生成が無効になり、デフォルトは true
#### lang
@ -243,15 +243,15 @@ abbrlink: theme-guide
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/banana.md -> example.com/es/posts/banana/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/orange.md -> example.com/ru/posts/orange/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink

View file

@ -231,7 +231,7 @@ abbrlink: theme-guide
#### toc
Включает оглавление. Эта функция еще не реализована.
Генерировать оглавление. При значении false автоматическая генерация отключается. По умолчанию: true.
#### lang
@ -243,15 +243,15 @@ abbrlink: theme-guide
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/banana.md -> example.com/es/posts/banana/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/orange.md -> example.com/ru/posts/orange/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink

View file

@ -231,7 +231,7 @@ abbrlink: theme-guide
#### toc
是否開啟目錄。尚未實現該功能
是否生成目錄。設為 false 時停用自動生成,預設為 true
#### lang
@ -243,15 +243,15 @@ abbrlink: theme-guide
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/banana.md -> example.com/es/posts/banana/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/orange.md -> example.com/ru/posts/orange/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink

View file

@ -231,7 +231,7 @@ abbrlink: theme-guide
#### toc
是否开启目录。尚未实现该功能
是否生成目录。设为 false 时关闭自动生成,默认为 true
#### lang
@ -243,15 +243,15 @@ abbrlink: theme-guide
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/banana.md -> example.com/es/posts/banana/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/orange.md -> example.com/ru/posts/orange/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink

View file

@ -6,6 +6,7 @@ export const ui = {
posts: '文章',
tags: '标签',
about: '关于',
toc: '目录',
},
'zh-tw': {
title: '重新編排',
@ -14,6 +15,7 @@ export const ui = {
posts: '文章',
tags: '標籤',
about: '關於',
toc: '目錄',
},
'ja': {
title: '再組版',
@ -22,6 +24,7 @@ export const ui = {
posts: '記事',
tags: 'タグ',
about: '概要',
toc: '目次',
},
'en': {
title: 'Retypeset',
@ -30,6 +33,7 @@ export const ui = {
posts: 'Posts',
tags: 'Tags',
about: 'About',
toc: 'Table of Contents',
},
'es': {
title: 'Retipografía',
@ -38,6 +42,7 @@ export const ui = {
posts: 'Artículos',
tags: 'Etiquetas',
about: 'Sobre',
toc: 'Índice',
},
'ru': {
title: 'Переверстка',
@ -46,5 +51,6 @@ export const ui = {
posts: 'Посты',
tags: 'Теги',
about: 'О себе',
toc: 'Оглавление',
},
}

View file

@ -3,6 +3,7 @@ import type { CollectionEntry } from 'astro:content'
import Comments from '@/components/Comments/index.astro'
import PostDate from '@/components/PostDate.astro'
import GoBack from '@/components/Widgets/GoBack.astro'
import TOC from '@/components/Widgets/TOC.astro'
import { allLocales, defaultLocale, moreLocales } from '@/config'
import { getTagPath } from '@/i18n/path'
import Layout from '@/layouts/Layout.astro'
@ -96,7 +97,7 @@ export async function getStaticPaths() {
const { post, lang, supportedLangs } = Astro.props
const description = generateDescription(post, 'meta')
const { Content, remarkPluginFrontmatter } = await post.render()
const { Content, headings, remarkPluginFrontmatter } = await post.render()
---
<Layout
@ -132,6 +133,8 @@ const { Content, remarkPluginFrontmatter } = await post.render()
minutes={remarkPluginFrontmatter.minutes}
/>
</div>
<!-- TOC -->
{post.data.toc && <TOC headings={headings} />}
<!-- Content -->
<Content />
</article>

View file

@ -5,7 +5,7 @@
}
html {
--at-apply: 'bg-background c-secondary antialiased scrollbar-hidden';
--at-apply: 'bg-background c-secondary antialiased scrollbar-hidden scroll-smooth';
}
html::-webkit-scrollbar {

View file

@ -18,165 +18,165 @@
}
/* Links */
.heti a {
.heti :where(a) {
--at-apply: 'underline decoration-secondary/40 underline-0.075em underline-offset-0.2em lg:underline-0.1em';
--at-apply: 'font-medium transition-colors tracking-0 hover:(c-primary decoration-secondary/80) ';
}
/* Paragraphs */
.heti p {
.heti :where(p) {
--at-apply: 'mt-3 mb-4 text-justify';
}
.heti p:not(:lang(zh)):not(:lang(ja)):not(:lang(ko)) {
.heti :where(p:not(:lang(zh)):not(:lang(ja)):not(:lang(ko))) {
--at-apply: 'text-start';
}
/* Headings */
.heti h1,
.heti h2,
.heti h3,
.heti h4,
.heti h5,
.heti h6 {
.heti :where(h1),
.heti :where(h2),
.heti :where(h3),
.heti :where(h4),
.heti :where(h5),
.heti :where(h6) {
--at-apply: 'mt-6 mb-3 font-semibold';
}
.heti h1 {
.heti :where(h1) {
--at-apply: 'text-8 leading-12';
}
.heti h2 {
.heti :where(h2) {
--at-apply: 'text-6 leading-9';
}
.heti h3 {
.heti :where(h3) {
--at-apply: 'text-5 leading-9';
}
.heti h4 {
.heti :where(h4) {
--at-apply: 'text-4.5 leading-6';
}
.heti h5 {
.heti :where(h5) {
--at-apply: 'text-4 leading-6';
}
.heti h6 {
.heti :where(h6) {
--at-apply: 'text-3.5 leading-6';
}
.heti h1,
.heti h2,
.heti h3 {
.heti :where(h1),
.heti :where(h2),
.heti :where(h3) {
--at-apply: 'tracking-0.05em';
}
.heti h1:not(:lang(zh)):not(:lang(ja)):not(:lang(ko)),
.heti h2:not(:lang(zh)):not(:lang(ja)):not(:lang(ko)),
.heti h3:not(:lang(zh)):not(:lang(ja)):not(:lang(ko)) {
.heti :where(h1:not(:lang(zh)):not(:lang(ja)):not(:lang(ko))),
.heti :where(h2:not(:lang(zh)):not(:lang(ja)):not(:lang(ko))),
.heti :where(h3:not(:lang(zh)):not(:lang(ja)):not(:lang(ko))) {
--at-apply: 'tracking-0';
}
.heti h1 + h2,
.heti h2 + h3,
.heti h3 + h4,
.heti h4 + h5,
.heti h5 + h6 {
.heti :where(h1 + h2),
.heti :where(h2 + h3),
.heti :where(h3 + h4),
.heti :where(h4 + h5),
.heti :where(h5 + h6) {
--at-apply: 'mt-3';
}
/* Blockquotes */
.heti blockquote {
.heti :where(blockquote) {
--at-apply: 'mt-3 mb-6 px-4 py-3 rounded';
--at-apply: 'border-l-4 border-solid border-secondary/25 bg-secondary/5';
}
.heti blockquote blockquote {
.heti blockquote :where(blockquote) {
--at-apply: 'my-3';
}
.heti blockquote p {
.heti blockquote :where(p) {
--at-apply: 'my-2';
}
/* Code Blocks */
.heti pre {
--at-apply: 'mt-3 mb-4 px-4 py-3 rounded bg-secondary/5! border border-solid border-secondary/7';
.heti :where(pre) {
--at-apply: 'mt-3 mb-4 px-4 py-3 rounded bg-secondary/5! border border-solid border-secondary/5';
--at-apply: 'overflow-auto whitespace-pre scrollbar-hidden';
}
.heti pre code {
.heti pre :where(code) {
--at-apply: 'p-0 bg-secondary/0 tracking-0 border-none';
}
html.dark .heti pre span {
html.dark .heti pre :where(span) {
--at-apply: 'text-[var(--shiki-dark)]!';
}
/* Inline Code */
.heti code {
--at-apply: 'p-0.5 bg-secondary/5 rounded text-0.85em border border-solid border-secondary/7';
.heti :where(code) {
--at-apply: 'p-0.5 bg-secondary/5 rounded text-0.85em border border-solid border-secondary/5';
}
/* Horizontal Rules */
.heti hr {
.heti :where(hr) {
--at-apply: 'border-secondary/25';
}
/* Lists */
.heti ul,
.heti ol,
.heti dl {
.heti :where(ul),
.heti :where(ol),
.heti :where(dl) {
--at-apply: 'mt-3 mb-6';
}
.heti ul,
.heti ol {
.heti :where(ul),
.heti :where(ol) {
--at-apply: 'pl-8';
}
.heti ul ul,
.heti ul ol,
.heti ol ul,
.heti ol ol {
.heti ul :where(ul),
.heti ul :where(ol),
.heti ol :where(ul),
.heti ol :where(ol) {
--at-apply: 'my-0';
}
.heti ul {
.heti :where(ul) {
--at-apply: 'list-disc';
}
.heti ol {
.heti :where(ol) {
--at-apply: 'list-decimal';
}
.heti ul ul,
.heti ol ul {
.heti ul :where(ul),
.heti ol :where(ul) {
--at-apply: 'list-circle';
}
.heti ul ul ul,
.heti ul ol ul,
.heti ol ul ul,
.heti ol ol ul {
.heti ul ul :where(ul),
.heti ul ol :where(ul),
.heti ol ul :where(ul),
.heti ol ol :where(ul) {
--at-apply: 'list-square';
}
.heti li {
.heti :where(li) {
--at-apply: 'list-unset';
}
/* Tables */
.heti table {
.heti :where(table) {
--at-apply: 'box-border table-fixed mt-3 mb-6 rounded-md break-words';
--at-apply: 'border border-solid border-secondary/25 border-collapse';
}
.heti th,
.heti td {
.heti :where(th),
.heti :where(td) {
--at-apply: 'px-3 py-1.5 border border-solid border-secondary/40';
}
/* Abbreviations */
.heti abbr {
.heti :where(abbr) {
--at-apply: 'tracking-0';
}
.heti abbr[title] {
.heti :where(abbr[title]) {
--at-apply: 'mx-0.25 pb-0.25 border-dotted border-secondary border-b-1 no-underline cursor-help';
}
/* Superscript and Subscript */
.heti sub,
.heti sup {
.heti :where(sub),
.heti :where(sup) {
--at-apply: 'mx-0.15em relative text-0.75em leading-1 align-baseline';
}
.heti sub {
.heti :where(sub) {
--at-apply: 'bottom--0.25em';
}
.heti sup {
.heti :where(sup) {
--at-apply: 'top--0.5em';
}
.heti sub a,
.heti sup a {
.heti sub :where(a),
.heti sup :where(a) {
--at-apply: 'no-underline';
}
.heti sup:target,
@ -189,16 +189,16 @@ html.dark .heti sup a:target {
}
/* Keyboard Input */
.heti kbd {
.heti :where(kbd) {
--at-apply: 'rounded border border-solid border-secondary/40 text-secondary';
--at-apply: 'inline-block text-0.85em font-bold leading-none px-1 py-0.75 whitespace-nowrap';
}
/* Highlighted Text */
.heti mark {
.heti :where(mark) {
--at-apply: 'mx-0.25 px-0.25 py-0.5 text-inherit bg-#ff0';
}
html.dark .heti mark {
html.dark .heti :where(mark) {
--at-apply: 'bg-#4d4a00e0';
}
@ -231,68 +231,68 @@ html.dark .heti mark {
content: "Сноски";
--at-apply: 'block text-5 font-semibold mt-6 mb-3';
}
.heti .data-footnote-backref {
.heti :where(.data-footnote-backref) {
--at-apply: 'no-underline';
}
/* Bold */
.heti b,
.heti strong {
.heti :where(b),
.heti :where(strong) {
--at-apply: 'font-semibold';
}
/* Italic */
.heti i {
.heti :where(i) {
--at-apply: 'font-italic';
}
/* Emphasized */
.heti em {
.heti :where(em) {
--at-apply: 'italic';
}
/* Quotes */
.heti q {
.heti :where(q) {
quotes: "「" "」" "『" "』";
}
.heti q:not(:lang(zh)):not(:lang(ja)):not(:lang(ko)) {
.heti :where(q:not(:lang(zh)):not(:lang(ja)):not(:lang(ko))) {
quotes: initial;
quotes: auto;
}
/* Wavy Underline */
.heti u {
.heti :where(u) {
--at-apply: 'mx-0.25 underline decoration-wavy decoration-red underline-offset-4';
}
html.dark .heti u {
html.dark .heti :where(u) {
--at-apply: 'decoration-#A14F50';
}
/* Strikethrough */
.heti del,
.heti s {
.heti :where(del),
.heti :where(s) {
--at-apply: 'mx-0.25';
}
/* Images */
.heti figure {
.heti :where(figure) {
--at-apply: 'my-6';
}
.heti figure > figcaption {
.heti figure > :where(figcaption) {
--at-apply: 'text-center text-sm mt-3 text-secondary/75';
}
/* Markdown Extensions Style >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
.heti details {
.heti :where(details) {
--at-apply: 'my-4 px-4 py-3 border border-solid border-secondary/25 rounded cursor-pointer';
}
.heti details summary {
.heti details :where(summary) {
--at-apply: 'cursor-pointer';
}
.heti details[open] summary {
.heti details[open] :where(summary) {
--at-apply: 'border-b border-solid border-secondary/25 mb-3 pb-3';
}
/* .heti details summary {
/* .heti details :where(summary) {
list-style: none;
}
.heti details summary::-webkit-details-marker {