mirror of
https://github.com/reonokiy/blog.nokiy.net.git
synced 2025-06-15 11:12:54 +02:00
Merge pull request #24 from radishzzz/dev
✨ feat: optimize performance, enhance animations and improve accessibility
- perf: replace overlayscrollbars with native scrollbar to fix page loading lag
- feat: implement GSAP animations throughout the site with optimized curves and durations
- style: refine scrollbar styling and heading margins for better visual consistency
- fix: resolve accessibility issues with footer links and improve mobile responsiveness
- refactor: reorganize CSS files and optimize DOM selectors for better performance
- chore: update dependencies and implement astro-compress
- docs: update README and theme guides
This commit is contained in:
commit
3d3e422ef2
63 changed files with 1697 additions and 2027 deletions
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -25,4 +25,4 @@ A clear and concise description of what you expected to happen.
|
|||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
### Additional context|补充信息
|
||||
Add any other context about the problem here.
|
||||
Add any other context about the problem here.
|
||||
|
|
81
.vscode/settings.json
vendored
81
.vscode/settings.json
vendored
|
@ -57,84 +57,5 @@
|
|||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"files.associations": {
|
||||
"*.mdx": "markdown"
|
||||
},
|
||||
"cSpell.words": [
|
||||
"abbrlink",
|
||||
"antfu",
|
||||
"apiflash",
|
||||
"apos",
|
||||
"Artículos",
|
||||
"astrodotbuild",
|
||||
"astrojs",
|
||||
"attributify",
|
||||
"backref",
|
||||
"belleza",
|
||||
"Beze",
|
||||
"Blockquotes",
|
||||
"blurhash",
|
||||
"bmoji",
|
||||
"canvaskit",
|
||||
"Cpath",
|
||||
"Csvg",
|
||||
"Disqus",
|
||||
"Etiquetas",
|
||||
"figcaption",
|
||||
"Frontmatter",
|
||||
"Fuwriu",
|
||||
"Giscus",
|
||||
"GSAP",
|
||||
"gtag",
|
||||
"hètí",
|
||||
"Heti",
|
||||
"katex",
|
||||
"Lightbox",
|
||||
"Macbook",
|
||||
"mdast",
|
||||
"Moeyua",
|
||||
"msrc",
|
||||
"msvalidate",
|
||||
"noopener",
|
||||
"noreferrer",
|
||||
"Noto",
|
||||
"oklch",
|
||||
"opengraph",
|
||||
"overlayscrollbars",
|
||||
"pagefind",
|
||||
"partytown",
|
||||
"photoswipe",
|
||||
"pswp",
|
||||
"radishzz",
|
||||
"rashomon",
|
||||
"rehype",
|
||||
"reimagines",
|
||||
"Retipografía",
|
||||
"Retypeset",
|
||||
"Reviviendo",
|
||||
"Roundhand",
|
||||
"Segoe",
|
||||
"Sentimentalisme",
|
||||
"Servetus",
|
||||
"shiki",
|
||||
"Sobre",
|
||||
"srcset",
|
||||
"STIX",
|
||||
"stylesheet",
|
||||
"tipográfica",
|
||||
"titlebar",
|
||||
"Twikoo",
|
||||
"Umami",
|
||||
"unocss",
|
||||
"unpic",
|
||||
"vite",
|
||||
"waline",
|
||||
"walinejs",
|
||||
"weibo",
|
||||
"Возрождая",
|
||||
"красоту",
|
||||
"Переверстка",
|
||||
"Посты",
|
||||
"себе",
|
||||
"Теги",
|
||||
"типографики"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
26
README.md
26
README.md
|
@ -42,7 +42,6 @@ Retypeset is a static blog theme based on the [Astro](https://astro.build/) fram
|
|||
## Performance
|
||||
|
||||
<br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://pagespeed.web.dev/analysis?url=https%3A%2F%2Fretypeset.radishzz.cc%2Fen%2F">
|
||||
<img width="710" alt="Retypeset Lighthouse Score" src="images/retypeset-lighthouse-score.svg">
|
||||
|
@ -52,15 +51,13 @@ Retypeset is a static blog theme based on the [Astro](https://astro.build/) fram
|
|||
## Getting Started
|
||||
|
||||
1. [Fork](https://github.com/radishzzz/astro-theme-retypeset/fork) this repository, or use this template to create a new repository.
|
||||
|
||||
2. Click the `Code` button, copy the `HTTPS` URL, and run the following commands in your terminal:
|
||||
|
||||
2. Run the following commands in your terminal:
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone repository-url
|
||||
git clone <repository-url>
|
||||
|
||||
# Navigate to the project directory
|
||||
cd repository-name
|
||||
cd <repository-name>
|
||||
|
||||
# Install pnpm globally (if not already installed)
|
||||
npm install -g pnpm
|
||||
|
@ -71,23 +68,14 @@ Retypeset is a static blog theme based on the [Astro](https://astro.build/) fram
|
|||
# Start the development server
|
||||
pnpm dev
|
||||
```
|
||||
3. Refer to the [Theme Guide](https://retypeset.radishzz.cc/en/posts/theme-guide/) to customize your blog and create new articles.
|
||||
4. Refer to the [Astro Deployment Guides](https://docs.astro.build/en/guides/deploy/) to deploy your blog to Netlify, Vercel, or other platforms.
|
||||
|
||||
3. Open [localhost:4321](http://localhost:4321/) in your browser to see a live preview of your website.
|
||||
|
||||
4. Refer to the [Theme Guide](https://retypeset.radishzz.cc/en/posts/theme-guide/) to customize your blog and create new articles.
|
||||
|
||||
5. Refer to the [Astro Deployment Guides](https://docs.astro.build/en/guides/deploy/) to deploy your blog to Netlify, Vercel, or other platforms.
|
||||
|
||||
 [](https://app.netlify.com/start)
|
||||
[](https://vercel.com/new)
|
||||
 [](https://app.netlify.com/start) [](https://vercel.com/new)
|
||||
|
||||
## Updates
|
||||
|
||||
- Retypeset releases [new features](https://github.com/radishzzz/astro-theme-retypeset/issues/18) from time to time, which can be updated as follows.
|
||||
|
||||
- Refer to the [GitHub Docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork) to run `Sync fork` in your repository to sync with the latest branch.
|
||||
|
||||
- Do not click `Discard Changes`, or you will lose your modifications.
|
||||
Retypeset releases [new features](https://github.com/radishzzz/astro-theme-retypeset/issues/18) from time to time. You can refer to the [GitHub Docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork) and run `Sync fork` in your repository to sync with the latest branch. Do not click `Discard Changes`, or you will lose your modifications.
|
||||
|
||||
## Credits
|
||||
|
||||
|
|
28
README.zh.md
28
README.zh.md
|
@ -2,7 +2,7 @@
|
|||
<img alt="Cover Image" src="images/retypeset-zh-mobile.webp"/>
|
||||
|
||||
<div align="center">
|
||||
<a title="en" href="README.md">
|
||||
<a title="en" href="https://github.com/radishzzz/astro-theme-retypeset?tab=readme-ov-file#retypeset">
|
||||
<img src="https://img.shields.io/badge/-English-545759?style=for-the-badge" alt="English">
|
||||
</a>
|
||||
<picture>
|
||||
|
@ -42,7 +42,6 @@ Retypeset 是一款基于 [Astro](https://astro.build/) 框架的静态博客主
|
|||
## 性能
|
||||
|
||||
<br>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://pagespeed.web.dev/analysis?url=https%3A%2F%2Fretypeset.radishzz.cc%2F">
|
||||
<img width="710" alt="Retypeset Lighthouse Score" src="images/retypeset-lighthouse-score.svg">
|
||||
|
@ -52,15 +51,13 @@ Retypeset 是一款基于 [Astro](https://astro.build/) 框架的静态博客主
|
|||
## 开始
|
||||
|
||||
1. [Fork](https://github.com/radishzzz/astro-theme-retypeset/fork) 此仓库,或使用此模版创建新仓库。
|
||||
|
||||
2. 点击 `Code` 按钮,复制 `HTTPS` 地址,在终端执行:
|
||||
|
||||
2. 在终端执行以下指令:
|
||||
```bash
|
||||
# 克隆仓库
|
||||
git clone 仓库地址
|
||||
git clone <仓库地址>
|
||||
|
||||
# 进入项目目录
|
||||
cd 仓库名称
|
||||
cd <仓库名称>
|
||||
|
||||
# 全局安装 pnpm(如果未安装)
|
||||
npm install -g pnpm
|
||||
|
@ -71,23 +68,14 @@ Retypeset 是一款基于 [Astro](https://astro.build/) 框架的静态博客主
|
|||
# 启动开发服务器
|
||||
pnpm dev
|
||||
```
|
||||
3. 参考 [主题上手指南](https://retypeset.radishzz.cc/posts/theme-guide/),自定义你的博客并创建新文章。
|
||||
4. 参考 [Astro 部署指南](https://docs.astro.build/zh-cn/guides/deploy/),将博客部署至 Netlify、Vercel 等平台。
|
||||
|
||||
3. 在浏览器中打开 [localhost:4321](http://localhost:4321/),查看网站的实时预览。
|
||||
|
||||
4. 参考 [主题上手指南](https://retypeset.radishzz.cc/posts/theme-guide/),自定义你的博客并创建新文章。
|
||||
|
||||
5. 参考 [Astro 部署指南](https://docs.astro.build/zh-cn/guides/deploy/),将博客部署至 Netlify、Vercel 等平台。
|
||||
|
||||
 [](https://app.netlify.com/start)
|
||||
[](https://vercel.com/new)
|
||||
 [](https://app.netlify.com/start) [](https://vercel.com/new)
|
||||
|
||||
## 更新
|
||||
|
||||
- Retypeset 会不定期发布 [新功能](https://github.com/radishzzz/astro-theme-retypeset/issues/18),更新方法如下。
|
||||
|
||||
- 参考 [GitHub 文档](https://docs.github.com/zh/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork),在仓库中执行 `Sync fork` 同步最新分支。
|
||||
|
||||
- 不要点击 `Discard Changes`,否则会丢失你的更改。
|
||||
Retypeset 会不定期发布 [新功能](https://github.com/radishzzz/astro-theme-retypeset/issues/18)。你可以参考 [GitHub 文档](https://docs.github.com/zh/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork),在仓库中执行 `Sync fork` 以同步最新分支。不要点击 `Discard Changes`,否则会丢失你的更改。
|
||||
|
||||
## 鸣谢
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import type { Element } from 'hast'
|
|||
import mdx from '@astrojs/mdx'
|
||||
import partytown from '@astrojs/partytown'
|
||||
import sitemap from '@astrojs/sitemap'
|
||||
import Compress from 'astro-compress'
|
||||
import robotsTxt from 'astro-robots-txt'
|
||||
import { defineConfig } from 'astro/config'
|
||||
import rehypeAutolinkHeadings from 'rehype-autolink-headings'
|
||||
|
@ -15,6 +16,7 @@ import UnoCSS from 'unocss/astro'
|
|||
import { themeConfig } from './src/config'
|
||||
import { langMap } from './src/i18n/config'
|
||||
import { rehypeImgToFigure } from './src/plugins/rehype-img-to-figure.mjs'
|
||||
import { rehypeUnwrapImg } from './src/plugins/rehype-unwrap-img.mjs'
|
||||
import { remarkAdmonitions } from './src/plugins/remark-admonitions.mjs'
|
||||
import { remarkGithubCard } from './src/plugins/remark-github-card.mjs'
|
||||
import { remarkReadingTime } from './src/plugins/remark-reading-time.mjs'
|
||||
|
@ -57,6 +59,13 @@ export default defineConfig({
|
|||
}),
|
||||
sitemap(),
|
||||
robotsTxt(),
|
||||
Compress({
|
||||
CSS: false,
|
||||
HTML: true, // Enable HTML compression only to remove comments
|
||||
Image: false,
|
||||
JavaScript: false,
|
||||
SVG: false,
|
||||
}),
|
||||
],
|
||||
markdown: {
|
||||
remarkPlugins: [
|
||||
|
@ -70,6 +79,7 @@ export default defineConfig({
|
|||
rehypeKatex,
|
||||
rehypeSlug,
|
||||
rehypeImgToFigure,
|
||||
rehypeUnwrapImg, // Must be after rehypeImgToFigure
|
||||
[
|
||||
rehypeAutolinkHeadings,
|
||||
{
|
||||
|
|
25
package.json
25
package.json
|
@ -2,7 +2,7 @@
|
|||
"name": "astro-theme-retypeset",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"packageManager": "pnpm@10.10.0",
|
||||
"packageManager": "pnpm@10.11.0",
|
||||
"repository": "https://github.com/radishzzz/astro-theme-retypeset",
|
||||
"scripts": {
|
||||
"dev": "astro check && astro dev",
|
||||
|
@ -10,23 +10,24 @@
|
|||
"preview": "astro preview",
|
||||
"astro": "astro",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint . --fix"
|
||||
"lint:fix": "eslint . --fix",
|
||||
"comments": "curl -L https://unpkg.com/@waline/client@latest/dist/waline.css -o public/assets/waline/waline.css && curl -L https://unpkg.com/@waline/client@latest/dist/waline.js -o public/assets/waline/waline.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^4.2.6",
|
||||
"@astrojs/partytown": "^2.1.4",
|
||||
"@astrojs/sitemap": "^3.4.0",
|
||||
"@waline/client": "^3.5.7",
|
||||
"astro": "^5.7.13",
|
||||
"astro-compress": "^2.3.8",
|
||||
"astro-og-canvas": "^0.7.0",
|
||||
"astro-robots-txt": "^1.0.0",
|
||||
"canvaskit-wasm": "^0.40.0",
|
||||
"feed": "^5.0.1",
|
||||
"gsap": "^3.13.0",
|
||||
"katex": "^0.16.22",
|
||||
"markdown-it": "^14.1.0",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"node-html-parser": "^7.0.1",
|
||||
"overlayscrollbars": "^2.11.2",
|
||||
"photoswipe": "^5.4.4",
|
||||
"reading-time": "^1.5.0",
|
||||
"rehype-autolink-headings": "^7.1.0",
|
||||
|
@ -35,26 +36,26 @@
|
|||
"rehype-slug": "^6.0.0",
|
||||
"remark-directive": "^4.0.0",
|
||||
"remark-math": "^6.0.0",
|
||||
"sanitize-html": "^2.16.0",
|
||||
"sanitize-html": "^2.17.0",
|
||||
"sharp": "^0.34.1",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^4.13.0",
|
||||
"@antfu/eslint-config": "^4.13.1",
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@types/node": "^22.15.17",
|
||||
"@types/node": "^22.15.18",
|
||||
"@types/sanitize-html": "^2.16.0",
|
||||
"@unocss/eslint-plugin": "66.1.1",
|
||||
"@unocss/preset-attributify": "66.1.1",
|
||||
"@unocss/reset": "66.1.1",
|
||||
"@unocss/eslint-plugin": "66.1.2",
|
||||
"@unocss/preset-attributify": "66.1.2",
|
||||
"@unocss/reset": "66.1.2",
|
||||
"astro-eslint-parser": "^1.2.2",
|
||||
"eslint": "^9.26.0",
|
||||
"eslint": "^9.27.0",
|
||||
"eslint-plugin-astro": "^1.3.1",
|
||||
"lint-staged": "^16.0.0",
|
||||
"typescript": "~5.8.3",
|
||||
"unocss": "66.1.1",
|
||||
"unocss": "66.1.2",
|
||||
"unocss-preset-theme": "^0.14.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
|
|
2169
pnpm-lock.yaml
generated
2169
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
1
public/assets/waline/waline.css
Normal file
1
public/assets/waline/waline.css
Normal file
File diff suppressed because one or more lines are too long
84
public/assets/waline/waline.js
Normal file
84
public/assets/waline/waline.js
Normal file
File diff suppressed because one or more lines are too long
91
public/fonts/EarlySummer-Split/EarlySummerSerif License.txt
Normal file
91
public/fonts/EarlySummer-Split/EarlySummerSerif License.txt
Normal file
|
@ -0,0 +1,91 @@
|
|||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@ -28,9 +28,9 @@ const nextUrl = useSupportedLangs
|
|||
|
||||
<div
|
||||
class:list={[
|
||||
'absolute flex gap-6 top-14.6 right-7.25vw min-[823px]:max-[1024px]:right-[calc(50vw-22rem)]',
|
||||
'absolute right-7.25vw top-14.6 flex gap-6 min-[823px]:max-[1024px]:right-[calc(50vw-22rem)]',
|
||||
'[@supports(-webkit-touch-callout:none)]:top-13.6', // fix position issue on ios
|
||||
'lg:(fixed w-14rem top-auto bottom-47 right-[max(5.625rem,calc(50vw-34.375rem))])',
|
||||
'lg:(fixed bottom-47 right-[max(5rem,calc(50vw-35rem))] top-auto w-14rem)',
|
||||
]}
|
||||
>
|
||||
<!-- Language Switcher -->
|
||||
|
@ -49,8 +49,9 @@ const nextUrl = useSupportedLangs
|
|||
|
||||
<!-- Theme Toggle -->
|
||||
<button
|
||||
id="theme-toggle-button"
|
||||
aria-label="Switch light/dark theme"
|
||||
class="button-theme-toggle aspect-square w-4 c-secondary active:scale-90 hover:c-primary"
|
||||
class="aspect-square w-4 c-secondary active:scale-90 hover:c-primary"
|
||||
>
|
||||
<ThemeToggleIcon
|
||||
aria-hidden="true"
|
||||
|
@ -69,7 +70,7 @@ function updateTheme() {
|
|||
// Get current theme
|
||||
const isDark = document.documentElement.classList.contains('dark')
|
||||
// Update meta theme color
|
||||
const metaThemeColor = document.querySelector('meta[name="theme-color"]')
|
||||
const metaThemeColor = document.head.querySelector('meta[name="theme-color"]')
|
||||
if (metaThemeColor) {
|
||||
metaThemeColor.setAttribute('content', isDark ? darkMode : lightMode)
|
||||
}
|
||||
|
@ -82,10 +83,10 @@ function updateTheme() {
|
|||
// Bind click event to the button
|
||||
function setupThemeToggle() {
|
||||
// Locate theme toggle button
|
||||
const themeToggleButtons = document.querySelectorAll('.button-theme-toggle')
|
||||
// Add click listener to each button
|
||||
themeToggleButtons.forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
const themeToggleButton = document.getElementById('theme-toggle-button')
|
||||
// Add click listener to the button
|
||||
if (themeToggleButton) {
|
||||
themeToggleButton.addEventListener('click', () => {
|
||||
// If browser doesn't support View Transitions API, update theme directly
|
||||
if (!document.startViewTransition) {
|
||||
updateTheme()
|
||||
|
@ -93,18 +94,18 @@ function setupThemeToggle() {
|
|||
}
|
||||
|
||||
// Temporarily add markers during animation to implement view transition and disable CSS transitions
|
||||
document.documentElement.style.setProperty('view-transition-name', 'theme-transition')
|
||||
document.documentElement.setAttribute('data-theme-transition', '')
|
||||
document.documentElement.style.setProperty('view-transition-name', 'animation-theme-toggle')
|
||||
document.documentElement.setAttribute('data-theme-changing', '')
|
||||
|
||||
// If browser supports View Transitions API, use it to update theme
|
||||
const themeTransition = document.startViewTransition(updateTheme)
|
||||
// Remove markers after animation
|
||||
themeTransition.finished.then(() => {
|
||||
document.documentElement.style.removeProperty('view-transition-name')
|
||||
document.documentElement.removeAttribute('data-theme-transition')
|
||||
document.documentElement.removeAttribute('data-theme-changing')
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize click event (on first load or page transition)
|
||||
|
|
|
@ -2,13 +2,6 @@
|
|||
import { defaultLocale, themeConfig } from '@/config'
|
||||
import { walineLocaleMap } from '@/i18n/config'
|
||||
|
||||
const {
|
||||
serverURL = '',
|
||||
emoji = [],
|
||||
search = false,
|
||||
imageUploader = false,
|
||||
} = themeConfig.comment?.waline ?? {}
|
||||
|
||||
// Get the language code of Waline
|
||||
function getWalineLang(currentPath: string, defaultLocale: string): string {
|
||||
// Extract language code from path
|
||||
|
@ -20,43 +13,46 @@ function getWalineLang(currentPath: string, defaultLocale: string): string {
|
|||
return walineLocaleMap[lang as keyof typeof walineLocaleMap]
|
||||
}
|
||||
|
||||
// Get Waline language and generate configuration json
|
||||
const walineLang = getWalineLang(Astro.url.pathname, defaultLocale)
|
||||
const walineConfigJson = JSON.stringify({
|
||||
serverURL,
|
||||
lang: walineLang,
|
||||
emoji,
|
||||
search,
|
||||
imageUploader,
|
||||
})
|
||||
const { waline: { serverURL = '', emoji = [], search = false, imageUploader = false } = {} } = themeConfig.comment ?? {}
|
||||
---
|
||||
|
||||
<div
|
||||
id="waline"
|
||||
class="mt-16"
|
||||
data-config={walineConfigJson}
|
||||
>
|
||||
</div>
|
||||
></div>
|
||||
|
||||
<!-- Not use is:inline or define:vars >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
|
||||
<script>
|
||||
import { init } from '@waline/client'
|
||||
import '@waline/client/style'
|
||||
<!-- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
|
||||
|
||||
<script
|
||||
is:inline
|
||||
define:vars={{
|
||||
walineLang,
|
||||
serverURL,
|
||||
emoji,
|
||||
search,
|
||||
imageUploader,
|
||||
}}
|
||||
type="module"
|
||||
>
|
||||
import { init } from '/assets/waline/waline.js'
|
||||
|
||||
function initWaline() {
|
||||
const walineEl = document.getElementById('waline')
|
||||
const walineConfig = JSON.parse(walineEl?.dataset.config || '{}')
|
||||
|
||||
init({
|
||||
el: '#waline',
|
||||
serverURL,
|
||||
// Share comments on posts in different languages
|
||||
path: window.location.pathname.replace(/^\/([a-z]{2}(-[a-z]{2})?)\//, '/'),
|
||||
lang: walineLang,
|
||||
emoji,
|
||||
dark: 'html.dark',
|
||||
requiredMeta: ['nick', 'mail'],
|
||||
highlighter: false,
|
||||
texRenderer: false,
|
||||
imageUploader,
|
||||
search,
|
||||
noCopyright: true,
|
||||
reaction: [],
|
||||
...walineConfig,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -79,13 +75,13 @@ document.addEventListener('astro:page-load', initWaline)
|
|||
--at-apply: 'leading-3.6 mt-1.4';
|
||||
}
|
||||
#waline .wl-panel {
|
||||
--at-apply: 'm-0 rounded border-secondary/25'
|
||||
--at-apply: 'm-0 rounded-lg border-secondary/25'
|
||||
}
|
||||
#waline .wl-header {
|
||||
--at-apply: 'p-0';
|
||||
}
|
||||
#waline .wl-header-item {
|
||||
border-bottom: 1px solid var(--waline-border-color);
|
||||
--at-apply: 'border-b border-solid border-primary/25';
|
||||
}
|
||||
#waline .wl-header label {
|
||||
--at-apply: 'text-3';
|
||||
|
@ -104,14 +100,11 @@ document.addEventListener('astro:page-load', initWaline)
|
|||
--at-apply: 'min-h-24';
|
||||
}
|
||||
#waline .wl-editor::placeholder {
|
||||
color: var(--waline-light-grey);
|
||||
--at-apply: 'c-primary/25';
|
||||
}
|
||||
#waline .wl-footer {
|
||||
--at-apply: 'm-2';
|
||||
}
|
||||
#waline .wl-info .wl-btn {
|
||||
--at-apply: 'rounded';
|
||||
}
|
||||
#waline .wl-text-number,
|
||||
#waline .wl-action[title="Markdown Guide"],
|
||||
#waline .wl-sort,
|
||||
|
@ -119,16 +112,10 @@ document.addEventListener('astro:page-load', initWaline)
|
|||
--at-apply: 'hidden';
|
||||
}
|
||||
#waline .wl-emoji-popup {
|
||||
--at-apply: 'start-0 rounded border-secondary/25';
|
||||
--at-apply: 'start-0 border-secondary/25 max-w-532px';
|
||||
}
|
||||
#waline .wl-emoji-popup .wl-tab-wrapper::-webkit-scrollbar {
|
||||
--at-apply: 'w-1.2';
|
||||
}
|
||||
#waline .wl-emoji-popup .wl-tab-wrapper::-webkit-scrollbar-thumb {
|
||||
background: oklch(var(--un-preset-theme-colors-secondary) / 0.25);
|
||||
}
|
||||
#waline .wl-emoji-popup .wl-tab-wrapper::-webkit-scrollbar-track-piece {
|
||||
--at-apply: 'bg-transparent';
|
||||
#waline .wl-emoji-popup .wl-tab-wrapper {
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
#waline .wl-gif-popup {
|
||||
--at-apply: 'border-secondary/25';
|
||||
|
@ -155,7 +142,7 @@ document.addEventListener('astro:page-load', initWaline)
|
|||
--at-apply: 'leading-6 text-3.5';
|
||||
}
|
||||
#waline .wl-time {
|
||||
color: oklch(var(--un-preset-theme-colors-primary) / 0.75);
|
||||
--at-apply: 'c-primary/75';
|
||||
}
|
||||
#waline .wl-edit,
|
||||
#waline .wl-delete {
|
||||
|
@ -167,7 +154,6 @@ document.addEventListener('astro:page-load', initWaline)
|
|||
</style>
|
||||
|
||||
<!-- Official CSS Variables >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
|
||||
<!-- https://waline.js.org/reference/client/style.html -->
|
||||
<style>
|
||||
#waline {
|
||||
/* Regular Colors */
|
||||
|
|
|
@ -10,39 +10,46 @@ const year = Number(startYear) === currentYear
|
|||
? startYear
|
||||
: `${startYear}-${currentYear}`
|
||||
|
||||
// i18n RSS Path
|
||||
// i18n RSS Feed Path
|
||||
const currentLang = getLangFromPath(Astro.url.pathname)
|
||||
const links = socialLinks.map((link) => {
|
||||
if (link.name === 'RSS') {
|
||||
return {
|
||||
...link,
|
||||
url: currentLang === defaultLocale ? link.url : `/${currentLang}${link.url}`,
|
||||
url: currentLang === defaultLocale
|
||||
? link.url
|
||||
: `/${currentLang}${link.url}`,
|
||||
}
|
||||
}
|
||||
if (link.name === 'Email') {
|
||||
return {
|
||||
...link,
|
||||
url: `mailto:${link.url}`,
|
||||
}
|
||||
}
|
||||
return link
|
||||
})
|
||||
|
||||
const footerLinkClass = 'highlight-hover footer-highlight-position-fix py-0.8 transition-colors after:bottom-0.15em hover:c-primary'
|
||||
---
|
||||
|
||||
<footer
|
||||
class="text-3 leading-4.75 font-navbar lg:text-3.5"
|
||||
class="mb-4 text-3 leading-1.25em font-navbar lg:(mb-0 text-3.5)"
|
||||
lg="uno-desktop-column bottom-20"
|
||||
>
|
||||
<p>
|
||||
{links.map((link, index) => (
|
||||
<>
|
||||
<a class="highlight-hover transition-colors hover:c-primary after:bottom-0!" href={link.url} target="_blank" rel="noopener noreferrer">
|
||||
{link.name}
|
||||
</a>
|
||||
{index < links.length - 1 && ' / '}
|
||||
<a class={footerLinkClass} href={link.url} target="_blank" rel="noopener noreferrer">{link.name}</a> {index < links.length - 1 && '/'}
|
||||
</>
|
||||
))}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Powered by <a class="highlight-hover transition-colors hover:c-primary after:bottom-0!" href="https://astro.build/" target="_blank" rel="noopener noreferrer">Astro</a> and <a class="highlight-hover transition-colors hover:c-primary after:bottom-0!" href="https://github.com/radishzzz/astro-theme-retypeset" target="_blank" rel="noopener noreferrer">Retypeset</a>
|
||||
© {year} {author}
|
||||
</p>
|
||||
|
||||
<p>
|
||||
© {year} {author}
|
||||
Powered by <a class={footerLinkClass} href="https://astro.build/" target="_blank" rel="noopener noreferrer">Astro</a> and <a class={footerLinkClass} href="https://github.com/radishzzz/astro-theme-retypeset" target="_blank" rel="noopener noreferrer">Retypeset</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
|
|
@ -32,7 +32,7 @@ const SubtitleTag = isPost ? 'div' : 'h2'
|
|||
<div
|
||||
class="box-content inline-block pr-1"
|
||||
transition:name={`site-title-${currentLang}`}
|
||||
data-disable-transition-on-theme
|
||||
data-disable-theme-transition
|
||||
>
|
||||
<a
|
||||
id="site-title-link"
|
||||
|
|
|
@ -10,7 +10,9 @@ const isTagActive = isTag
|
|||
const isAboutActive = isAbout
|
||||
|
||||
function getNavItemClass(isActive: boolean) {
|
||||
return isActive ? 'font-bold c-primary highlight-static' : 'hover:(c-primary font-bold) transition-all highlight-hover'
|
||||
return isActive
|
||||
? 'highlight-static c-primary font-bold after:bottom-0.5em'
|
||||
: 'highlight-hover transition-colors transition-font-weight after:bottom-0.5em hover:(c-primary font-bold)'
|
||||
}
|
||||
|
||||
const navItems = [
|
||||
|
@ -36,8 +38,8 @@ const navItems = [
|
|||
aria-label="Site Navigation"
|
||||
class:list={[
|
||||
isPost ? 'hidden lg:block' : '',
|
||||
'mb-10.5 text-3.6 font-semibold leading-8.75 font-navbar',
|
||||
'lg:(uno-desktop-column text-4 leading-9.72 bottom-50) cjk:tracking-0.02em',
|
||||
'mb-10.5 text-3.6 font-semibold leading-2.45em font-navbar',
|
||||
'lg:(uno-desktop-column text-4 bottom-50) cjk:tracking-0.02em',
|
||||
]}
|
||||
>
|
||||
<ul>
|
||||
|
@ -45,7 +47,7 @@ const navItems = [
|
|||
<li>
|
||||
<a
|
||||
href={getLocalizedPath(item.href)}
|
||||
class={item.className}
|
||||
class={`${item.className} navbar-highlight-position-fix`}
|
||||
>
|
||||
{item.label}
|
||||
</a>
|
||||
|
|
|
@ -37,13 +37,13 @@ function getPostPath(post: Post) {
|
|||
>
|
||||
|
||||
{/* post title */}
|
||||
<h3 class="inline">
|
||||
<h3 class="inline transition-colors hover:c-primary">
|
||||
<a
|
||||
class="hover:c-primary cjk:tracking-0.02em"
|
||||
class="cjk:tracking-0.02em"
|
||||
lg={isHome ? 'font-medium text-4.5' : ''}
|
||||
href={getPostPath(post)}
|
||||
transition:name={`post-${post.data.abbrlink || post.id}-${lang}`}
|
||||
data-disable-transition-on-theme
|
||||
data-disable-theme-transition
|
||||
>
|
||||
{post.data.title}
|
||||
</a>
|
||||
|
@ -60,9 +60,9 @@ function getPostPath(post: Post) {
|
|||
|
||||
{/* mobile post time */}
|
||||
<div
|
||||
class="text-3.5 leading-6.875 font-time lg:hidden"
|
||||
class="py-0.8 text-3.5 font-time lg:hidden"
|
||||
transition:name={`time-${post.data.abbrlink || post.id}-${lang}`}
|
||||
data-disable-transition-on-theme
|
||||
data-disable-theme-transition
|
||||
>
|
||||
<PostDate
|
||||
date={post.data.published}
|
||||
|
@ -71,7 +71,7 @@ function getPostPath(post: Post) {
|
|||
</div>
|
||||
|
||||
{/* desktop post time */}
|
||||
<div class="hidden text-3.65 leading-6.875 font-time lg:(ml-2.5 inline)">
|
||||
<div class="hidden text-3.65 font-time lg:(ml-2.5 inline)">
|
||||
<PostDate
|
||||
date={post.data.published}
|
||||
minutes={post.remarkPluginFrontmatter.minutes}
|
||||
|
@ -82,7 +82,7 @@ function getPostPath(post: Post) {
|
|||
{isHome && (
|
||||
<div
|
||||
class="heti hidden"
|
||||
lg="mt-2 block"
|
||||
lg="mt-2.25 block"
|
||||
>
|
||||
<p>{generateDescription(post, 'list')}</p>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@ import GoBackIcon from '@/assets/icons/go-back.svg';
|
|||
<button
|
||||
id="back-button"
|
||||
class="hidden"
|
||||
lg="block absolute c-secondary/40 left--10 top-1/2 aspect-square w-4.5 translate-y--1/2 transition-colors ease-out c-secondary active:scale-90 hover:c-primary/80"
|
||||
lg="block absolute c-secondary/40 left--10 top-1/2 aspect-square w-4.5 translate-y--1/2 transition-colors ease-out c-secondary active:scale-90! hover:c-secondary/80"
|
||||
aria-label="Go back"
|
||||
>
|
||||
<GoBackIcon
|
|
@ -8,7 +8,7 @@
|
|||
<button
|
||||
id="back-to-top-button"
|
||||
aria-label="Back to top"
|
||||
class="fixed bottom-8 right-8 h-10 w-10 rounded-full bg-background transition-all duration-300 ease-out"
|
||||
class="fixed bottom-8 right-8 h-10 w-10 rounded-full bg-background transition-all ease-out"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<script>
|
||||
function setupGithubCards() {
|
||||
const githubCards = document.querySelectorAll('.gc-container')
|
||||
const githubCards = document.getElementsByClassName('gc-container')
|
||||
if (githubCards.length === 0)
|
||||
return
|
||||
|
||||
// Create an intersection observer to lazy load GitHub repo data when cards enter viewport
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
|
@ -13,7 +14,7 @@ function setupGithubCards() {
|
|||
})
|
||||
}, { rootMargin: '400px' })
|
||||
|
||||
githubCards.forEach(card => observer.observe(card))
|
||||
Array.from(githubCards).forEach(card => observer.observe(card))
|
||||
}
|
||||
|
||||
async function loadCardData(card: HTMLElement) {
|
||||
|
@ -21,11 +22,11 @@ async function loadCardData(card: HTMLElement) {
|
|||
if (!repo)
|
||||
return
|
||||
|
||||
const avatarEl = card.querySelector('.gc-owner-avatar') as HTMLElement
|
||||
const descEl = card.querySelector('.gc-repo-description') as HTMLElement
|
||||
const starsEl = card.querySelector('.gc-stars-count') as HTMLElement
|
||||
const forksEl = card.querySelector('.gc-forks-count') as HTMLElement
|
||||
const licenseEl = card.querySelector('.gc-license-info') as HTMLElement
|
||||
const avatarEl = card.getElementsByClassName('gc-owner-avatar')[0] as HTMLElement
|
||||
const descEl = card.getElementsByClassName('gc-repo-description')[0] as HTMLElement
|
||||
const starsEl = card.getElementsByClassName('gc-stars-count')[0] as HTMLElement
|
||||
const forksEl = card.getElementsByClassName('gc-forks-count')[0] as HTMLElement
|
||||
const licenseEl = card.getElementsByClassName('gc-license-info')[0] as HTMLElement
|
||||
|
||||
try {
|
||||
const response = await fetch(`https://api.github.com/repos/${repo}`)
|
||||
|
|
99
src/components/Widgets/GsapAnimation.astro
Normal file
99
src/components/Widgets/GsapAnimation.astro
Normal file
|
@ -0,0 +1,99 @@
|
|||
<script>
|
||||
import { gsap } from 'gsap'
|
||||
|
||||
function setupPostPageAnimation() {
|
||||
const allElements = Array.from(document.querySelectorAll('#gsap-post-page-content > *, #gsap-post-page-tags, #waline'))
|
||||
const tocList = document.getElementById('toc-list')
|
||||
const tocListChildren = tocList ? Array.from(tocList.children) : []
|
||||
const dateElement = document.getElementById('gsap-post-page-date')
|
||||
const backButton = document.getElementById('back-button')
|
||||
const tocIcon = document.getElementById('toc-icon')
|
||||
const tocContainer = document.getElementById('toc-container')
|
||||
|
||||
const isLargeScreen = window.matchMedia('(min-width: 1024px)').matches
|
||||
const isSmallScreen = window.matchMedia('(max-width: 1535px)').matches
|
||||
|
||||
// Post Content + Tags + Comments
|
||||
// First 15 elements
|
||||
gsap.from(allElements.slice(0, 15), {
|
||||
opacity: 0,
|
||||
y: '2rem',
|
||||
duration: 0.3,
|
||||
delay: 0.1,
|
||||
ease: 'power2.out',
|
||||
stagger: 0.05,
|
||||
})
|
||||
// Rest elements as the 16 element
|
||||
if (allElements.length > 15) {
|
||||
gsap.from(allElements.slice(15), {
|
||||
opacity: 0,
|
||||
y: '2rem',
|
||||
duration: 0.3,
|
||||
delay: 0.1 + 0.05 * 15,
|
||||
ease: 'power2.out',
|
||||
})
|
||||
}
|
||||
|
||||
// Desktop Animations
|
||||
if (isLargeScreen) {
|
||||
// Post Date
|
||||
if (dateElement) {
|
||||
gsap.from(dateElement, {
|
||||
opacity: 0,
|
||||
y: '1rem',
|
||||
duration: 0.3,
|
||||
delay: 0.1,
|
||||
ease: 'power2.out',
|
||||
})
|
||||
}
|
||||
|
||||
// TOC Icon
|
||||
if (tocIcon) {
|
||||
gsap.from(tocIcon, {
|
||||
opacity: 0,
|
||||
y: '0.5rem',
|
||||
duration: 0.3,
|
||||
delay: 0.125,
|
||||
ease: 'power2.out',
|
||||
})
|
||||
}
|
||||
|
||||
// Toc List
|
||||
if (tocListChildren.length > 0) {
|
||||
gsap.from(tocListChildren, {
|
||||
opacity: 0,
|
||||
y: '1rem',
|
||||
duration: 0.3,
|
||||
delay: 0.15,
|
||||
ease: 'power2.out',
|
||||
stagger: 0.025,
|
||||
})
|
||||
}
|
||||
|
||||
// Back Button
|
||||
if (backButton) {
|
||||
gsap.from(backButton, {
|
||||
opacity: 0,
|
||||
x: '0.5rem',
|
||||
duration: 0.3,
|
||||
delay: 0.15,
|
||||
ease: 'power2.out',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Mobile Animation (for screens smaller than 1536px)
|
||||
if (isSmallScreen && tocContainer) {
|
||||
gsap.from(tocContainer, {
|
||||
opacity: 0,
|
||||
y: '2rem',
|
||||
duration: 0.3,
|
||||
delay: 0.1,
|
||||
ease: 'power2.out',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
setupPostPageAnimation()
|
||||
document.addEventListener('astro:after-swap', setupPostPageAnimation)
|
||||
</script>
|
|
@ -10,7 +10,8 @@ function setupPhotoSwipe() {
|
|||
if (bodyElement.hasAttribute('data-photoswipe-initialized'))
|
||||
return
|
||||
|
||||
const images = document.querySelectorAll('article.heti img')
|
||||
const article = document.querySelector('article.heti')
|
||||
const images = article ? article.getElementsByTagName('img') : []
|
||||
if (images.length === 0)
|
||||
return
|
||||
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
<script>
|
||||
import { OverlayScrollbars } from 'overlayscrollbars'
|
||||
|
||||
function setupScrollbar() {
|
||||
// Add scrollbar to body
|
||||
const bodyElement = document.body
|
||||
if (!bodyElement.hasAttribute('data-scrollbar-initialized')) {
|
||||
OverlayScrollbars({
|
||||
target: bodyElement,
|
||||
cancel: {
|
||||
nativeScrollbarsOverlaid: true,
|
||||
},
|
||||
}, {
|
||||
scrollbars: {
|
||||
theme: 'scrollbar-body',
|
||||
autoHide: 'scroll',
|
||||
autoHideDelay: 800,
|
||||
},
|
||||
overflow: {
|
||||
x: 'hidden',
|
||||
},
|
||||
})
|
||||
|
||||
bodyElement.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,
|
||||
}, {
|
||||
scrollbars: {
|
||||
theme: 'scrollbar-widget',
|
||||
autoHide: 'never',
|
||||
},
|
||||
overflow: {
|
||||
x: 'hidden',
|
||||
},
|
||||
})
|
||||
|
||||
tocElement.setAttribute('data-scrollbar-initialized', 'true')
|
||||
}
|
||||
|
||||
// Add scrollbar to code blocks
|
||||
const preElements = document.querySelectorAll('pre')
|
||||
preElements.forEach((pre) => {
|
||||
if (!pre.hasAttribute('data-scrollbar-initialized')) {
|
||||
OverlayScrollbars({
|
||||
target: pre,
|
||||
}, {
|
||||
scrollbars: {
|
||||
theme: 'scrollbar-widget',
|
||||
autoHide: 'leave',
|
||||
autoHideDelay: 500,
|
||||
},
|
||||
overflow: {
|
||||
y: 'hidden',
|
||||
},
|
||||
})
|
||||
|
||||
pre.setAttribute('data-scrollbar-initialized', 'true')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setupScrollbar()
|
||||
document.addEventListener('astro:after-swap', setupScrollbar)
|
||||
</script>
|
||||
|
||||
<style is:global>
|
||||
@import 'overlayscrollbars/overlayscrollbars.css';
|
||||
|
||||
.scrollbar-body {
|
||||
--os-size: 0.8rem;
|
||||
--os-padding-perpendicular: 0.15rem;
|
||||
--os-padding-axis: 0.2rem;
|
||||
--os-handle-border-radius: 99rem;
|
||||
--os-handle-perpendicular-size: 75%;
|
||||
--os-handle-perpendicular-size-hover: 100%;
|
||||
--os-handle-perpendicular-size-active: 100%;
|
||||
--os-handle-interactive-area-offset: 0.2rem;
|
||||
--os-handle-bg: oklch(var(--un-preset-theme-colors-secondary) / 0.25);
|
||||
--os-handle-bg-hover: oklch(var(--un-preset-theme-colors-secondary) / 0.40);
|
||||
--os-handle-bg-active: oklch(var(--un-preset-theme-colors-secondary) / 0.40);
|
||||
--os-handle-max-size: 80%;
|
||||
--os-handle-min-size: 12%;
|
||||
}
|
||||
|
||||
.scrollbar-widget {
|
||||
--os-size: 0.4rem;
|
||||
--os-padding-perpendicular: 0;
|
||||
--os-padding-axis: 0.05rem;
|
||||
--os-handle-border-radius: 99rem;
|
||||
--os-handle-perpendicular-size: 75%;
|
||||
--os-handle-perpendicular-size-hover: 100%;
|
||||
--os-handle-perpendicular-size-active: 100%;
|
||||
--os-handle-interactive-area-offset: 0.2rem;
|
||||
--os-handle-bg: oklch(var(--un-preset-theme-colors-secondary) / 0.15);
|
||||
--os-handle-bg-hover: oklch(var(--un-preset-theme-colors-secondary) / 0.30);
|
||||
--os-handle-bg-active: oklch(var(--un-preset-theme-colors-secondary) / 0.30);
|
||||
--os-handle-min-size: 12%;
|
||||
}
|
||||
|
||||
@media (min-width: 1536px) {
|
||||
#toc-content .os-scrollbar {
|
||||
--at-apply: 'hidden';
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -19,38 +19,51 @@ const filteredHeadings = headings.filter(heading =>
|
|||
---
|
||||
|
||||
{filteredHeadings.length > 0 && (
|
||||
<div class="mb-4 uno-round-border bg-secondary/5 2xl:(fixed left-0 top-43.5 max-w-[min(calc(50vw-38rem),13rem)] border-none bg-transparent)">
|
||||
// TOC Container
|
||||
<div
|
||||
id="toc-container"
|
||||
class="mb-4 uno-round-border bg-secondary/5 2xl:(fixed left-0 top-43.5 max-w-[min(calc(50vw-38rem),13rem)] border-none bg-secondary/0)"
|
||||
>
|
||||
{/* Hidden Checkbox */}
|
||||
<input
|
||||
type="checkbox"
|
||||
id="toc-toggle"
|
||||
class="accordion-toggle"
|
||||
hidden
|
||||
/>
|
||||
<div class="relative h-12 w-full bg-transparent">
|
||||
{/* TOC Toggle */}
|
||||
<div class="relative h-12 w-full">
|
||||
<label
|
||||
for="toc-toggle"
|
||||
class="absolute inset-0 flex cursor-pointer items-center 2xl:(static flex c-secondary/40 transition-colors ease-out hover:c-secondary/80)"
|
||||
>
|
||||
{/* Title on Mobile */}
|
||||
<span class="toc-title">
|
||||
{currentUI.toc}
|
||||
</span>
|
||||
|
||||
{/* Icon on Desktop */}
|
||||
<TocIcon
|
||||
id="toc-icon"
|
||||
aria-hidden="true"
|
||||
class="ml-4 hidden aspect-square w-4.2 2xl:(mt-4 block origin-center active:scale-90)"
|
||||
class="ml-1 hidden aspect-square w-4.2 2xl:(mt-4 block origin-center active:scale-90!)"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* Expandable content wrapper */}
|
||||
{/* Expandable Content Wrapper with Accordion Animation */}
|
||||
<div class="accordion-wrapper">
|
||||
<nav
|
||||
id="toc-content"
|
||||
class="accordion-content"
|
||||
aria-label="Table of Contents"
|
||||
>
|
||||
<ul class="toc-list">
|
||||
{/* TOC List */}
|
||||
<ul
|
||||
id="toc-list"
|
||||
class="toc-list"
|
||||
>
|
||||
{filteredHeadings.map(heading => (
|
||||
<li
|
||||
class:list={{
|
||||
|
@ -80,21 +93,21 @@ const filteredHeadings = headings.filter(heading =>
|
|||
<!-- Override heti default styles >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
|
||||
<style>
|
||||
.toc-title {
|
||||
--at-apply: 'font-semibold ml-4 select-none 2xl:hidden';
|
||||
--at-apply: 'font-semibold ml-4 2xl:hidden';
|
||||
}
|
||||
.toc-list {
|
||||
--at-apply: 'list-none pl-0 space-y-2 mt-1 mb-4 2xl:space-y-1.2';
|
||||
--at-apply: 'list-none pb-3.3 pl-0 space-y-2 mt-1 mb-4 2xl:space-y-1.2';
|
||||
}
|
||||
.toc-link-h2, .toc-link-h3, .toc-link-h4 {
|
||||
--at-apply: 'text-sm no-underline font-normal text-balance select-none 2xl:(text-3.2 c-secondary/60 transition-colors ease-in hover:(c-secondary font-medium))';
|
||||
--at-apply: 'text-sm no-underline font-normal text-balance 2xl:(text-3.2 c-secondary/60 transition-colors transition-font-weight duration-300 ease-out hover:(c-secondary font-medium))';
|
||||
}
|
||||
|
||||
/* Initial collapsed state with zero height grid row */
|
||||
.accordion-wrapper {
|
||||
--at-apply: 'grid rows-[0fr] duration-300 ease-in-out';
|
||||
--at-apply: 'grid rows-[0fr] transition-all duration-350 ease-in-out';
|
||||
}
|
||||
.accordion-content {
|
||||
--at-apply: 'overflow-hidden max-h-66 2xl:(max-h-[calc(100vh-21.5rem)]) pl-4 pr-6';
|
||||
--at-apply: 'max-h-66 overflow-hidden pl-4 pr-6 2xl:(max-h-[calc(100vh-26rem)] pl-1)';
|
||||
}
|
||||
|
||||
/* When toggle is checked, expand the wrapper to show content */
|
||||
|
@ -104,6 +117,10 @@ const filteredHeadings = headings.filter(heading =>
|
|||
.accordion-toggle:checked ~ .accordion-wrapper .accordion-content {
|
||||
--at-apply: 'overflow-y-auto';
|
||||
}
|
||||
#toc-content {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: oklch(var(--un-preset-theme-colors-secondary) / 0.15) transparent;
|
||||
}
|
||||
|
||||
@media (min-width: 1536px) {
|
||||
.accordion-wrapper {
|
||||
|
@ -121,6 +138,12 @@ const filteredHeadings = headings.filter(heading =>
|
|||
.toc-link-active {
|
||||
--at-apply: 'c-secondary font-medium';
|
||||
}
|
||||
#toc-content {
|
||||
--at-apply: 'scrollbar-hidden';
|
||||
}
|
||||
#toc-content::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -131,7 +154,7 @@ function setupTOCHighlight() {
|
|||
if (!tocContent)
|
||||
return
|
||||
|
||||
const tocLinks = tocContent.querySelectorAll('a')
|
||||
const tocLinks = tocContent.getElementsByTagName('a')
|
||||
if (tocLinks.length === 0)
|
||||
return
|
||||
|
||||
|
@ -140,7 +163,7 @@ function setupTOCHighlight() {
|
|||
|
||||
// Build mapping from heading IDs to TOC links
|
||||
const headingMap = new Map<string, HTMLAnchorElement>()
|
||||
tocLinks.forEach((link) => {
|
||||
Array.from(tocLinks).forEach((link) => {
|
||||
const id = link.getAttribute('href')?.substring(1)
|
||||
if (id)
|
||||
headingMap.set(id, link as HTMLAnchorElement)
|
||||
|
|
|
@ -60,6 +60,8 @@ export const themeConfig: ThemeConfig = {
|
|||
dateFormat: 'YYYY-MM-DD', // YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
|
||||
// enable KaTeX for mathematical formulas rendering
|
||||
katex: true, // true, false
|
||||
// enable table of contents for all posts by default
|
||||
toc: true, // true, false
|
||||
},
|
||||
// GLOBAL SETTINGS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> END
|
||||
|
||||
|
@ -139,16 +141,16 @@ export const themeConfig: ThemeConfig = {
|
|||
url: 'https://github.com/radishzzz/astro-theme-retypeset',
|
||||
},
|
||||
{
|
||||
name: 'X',
|
||||
url: 'https://x.com/radishzz_',
|
||||
},
|
||||
name: 'Email',
|
||||
url: 'email@radishzz.cc',
|
||||
}
|
||||
// {
|
||||
// name: 'Email',
|
||||
// url: 'https://example@gmail.com',
|
||||
// }
|
||||
// name: 'X',
|
||||
// url: 'https://x.com/radishzz_',
|
||||
// },
|
||||
],
|
||||
// year of website start
|
||||
startYear: 2024,
|
||||
startYear: 2025,
|
||||
},
|
||||
// FOOTER SETTINGS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> END
|
||||
|
||||
|
@ -157,8 +159,6 @@ export const themeConfig: ThemeConfig = {
|
|||
// link prefetch
|
||||
// docs: https://docs.astro.build/en/guides/prefetch/#prefetch-strategies
|
||||
linkPrefetch: 'viewport', // hover, tap, viewport, load
|
||||
// comment server url
|
||||
commentURL: 'https://retypeset-comment.radishzz.cc',
|
||||
// image hosting url
|
||||
imageHostURL: 'https://image.radishzz.cc',
|
||||
// custom google analytics js
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { allLocales } from '@/config'
|
||||
import { glob } from 'astro/loaders'
|
||||
import { defineCollection, z } from 'astro:content'
|
||||
import { allLocales, themeConfig } from '@/config'
|
||||
|
||||
const posts = defineCollection({
|
||||
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/posts' }),
|
||||
|
@ -15,7 +15,7 @@ const posts = defineCollection({
|
|||
// Advanced
|
||||
draft: z.boolean().optional().default(false),
|
||||
pin: z.number().int().min(0).max(99).optional().default(0),
|
||||
toc: z.boolean().optional().default(true),
|
||||
toc: z.boolean().optional().default(themeConfig.global.toc),
|
||||
lang: z.enum(['', ...allLocales]).optional().default(''),
|
||||
abbrlink: z.string().optional().default('').refine(
|
||||
abbrlink => !abbrlink || /^[a-z0-9\-]*$/.test(abbrlink),
|
||||
|
|
|
@ -17,7 +17,7 @@ $$
|
|||
t=\frac{1}{|G|}\sum_{g\in G}|\text{Fix}(g)|
|
||||
$$
|
||||
|
||||
For each integer $n\ge2$, the quotient group $\mathbb{Z}/n\mathbb{Z}$ is a cyclic group generated by $1+n\mathbb{Z}$ and so $\color{red}{\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n}$.
|
||||
For each integer $n\ge2$, the quotient group $\mathbb{Z}/n\mathbb{Z}$ is a cyclic group generated by $1+n\mathbb{Z}$ and so $\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n$.
|
||||
|
||||
The quotient group $\mathbb{R}/\mathbb{Z}$ is isomorphic to $([0,1),+_1)$, the group of real numbers in the interval $[0,1)$, under addition modulo 1.
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ $$
|
|||
t=\frac{1}{|G|}\sum_{g\in G}|\text{Fix}(g)|
|
||||
$$
|
||||
|
||||
Para cada entero $n\ge2$, el grupo cociente $\mathbb{Z}/n\mathbb{Z}$ es un grupo cíclico generado por $1+n\mathbb{Z}$ y por tanto $\color{red}{\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n}$.
|
||||
Para cada entero $n\ge2$, el grupo cociente $\mathbb{Z}/n\mathbb{Z}$ es un grupo cíclico generado por $1+n\mathbb{Z}$ y por tanto $\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n$.
|
||||
|
||||
El grupo cociente $\mathbb{R}/\mathbb{Z}$ es isomorfo a $([0,1),+_1)$, el grupo de números reales en el intervalo $[0,1)$, bajo la adición módulo 1.
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ $$
|
|||
t=\frac{1}{|G|}\sum_{g\in G}|\text{Fix}(g)|
|
||||
$$
|
||||
|
||||
各整数 $n\ge2$ に対して、商群 $\mathbb{Z}/n\mathbb{Z}$ は $1+n\mathbb{Z}$ によって生成される巡回群であり、したがって $\color{red}{\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n}$ となります。
|
||||
各整数 $n\ge2$ に対して、商群 $\mathbb{Z}/n\mathbb{Z}$ は $1+n\mathbb{Z}$ によって生成される巡回群であり、したがって $\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n$ となります。
|
||||
|
||||
商群 $\mathbb{R}/\mathbb{Z}$ は $([0,1),+_1)$ と同型です。これは区間 $[0,1)$ 上の実数のモジュロ1の加法群です。
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ $$
|
|||
t=\frac{1}{|G|}\sum_{g\in G}|\text{Fix}(g)|
|
||||
$$
|
||||
|
||||
Для каждого целого числа $n\ge2$ фактор-группа $\mathbb{Z}/n\mathbb{Z}$ является циклической группой, порождённой элементом $1+n\mathbb{Z}$, и поэтому $\color{red}{\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n}$.
|
||||
Для каждого целого числа $n\ge2$ фактор-группа $\mathbb{Z}/n\mathbb{Z}$ является циклической группой, порождённой элементом $1+n\mathbb{Z}$, и поэтому $\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n$.
|
||||
|
||||
Фактор-группа $\mathbb{R}/\mathbb{Z}$ изоморфна $([0,1),+_1)$, группе вещественных чисел в интервале $[0,1)$ с операцией сложения по модулю 1.
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ $$
|
|||
t=\frac{1}{|G|}\sum_{g\in G}|\text{Fix}(g)|
|
||||
$$
|
||||
|
||||
對於每個整數 $n\ge2$,商群 $\mathbb{Z}/n\mathbb{Z}$ 是由 $1+n\mathbb{Z}$ 生成的循環群,因此 $\color{red}{\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n}$。
|
||||
對於每個整數 $n\ge2$,商群 $\mathbb{Z}/n\mathbb{Z}$ 是由 $1+n\mathbb{Z}$ 生成的循環群,因此 $\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n$。
|
||||
|
||||
商群 $\mathbb{R}/\mathbb{Z}$ 同構於 $([0,1),+_1)$,即區間 $[0,1)$ 上以 1 為模的實數加法群。
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ $$
|
|||
t=\frac{1}{|G|}\sum_{g\in G}|\text{Fix}(g)|
|
||||
$$
|
||||
|
||||
对于每个整数 $n\ge2$,商群 $\mathbb{Z}/n\mathbb{Z}$ 是由 $1+n\mathbb{Z}$ 生成的循环群,因此 $\color{red}{\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n}$。
|
||||
对于每个整数 $n\ge2$,商群 $\mathbb{Z}/n\mathbb{Z}$ 是由 $1+n\mathbb{Z}$ 生成的循环群,因此 $\mathbb{Z}/n\mathbb{Z}\cong\mathbb{Z}_n$。
|
||||
|
||||
商群 $\mathbb{R}/\mathbb{Z}$ 同构于 $([0,1),+_1)$,即区间 $[0,1)$ 上以 1 为模的实数加法群。
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ To create automatic figure captions, use the standard Markdown image syntax `
|
||||

|
||||
|
||||

|
||||

|
||||
```
|
||||
|
||||
### Output
|
||||
|
|
|
@ -17,9 +17,9 @@ Para crear leyendas automáticas para figuras, utilice la sintaxis estándar de
|
|||
### Sintaxis
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
```
|
||||
|
||||
### Resultado
|
||||
|
|
|
@ -17,9 +17,9 @@ abbrlink: markdown-extended-features
|
|||
### 構文
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
```
|
||||
|
||||
### 効果
|
||||
|
|
|
@ -17,9 +17,9 @@ abbrlink: markdown-extended-features
|
|||
### Синтаксис
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
```
|
||||
|
||||
### Результат
|
||||
|
|
|
@ -17,9 +17,9 @@ abbrlink: markdown-extended-features
|
|||
### 語法
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
```
|
||||
|
||||
### 效果
|
||||
|
|
|
@ -17,9 +17,9 @@ abbrlink: markdown-extended-features
|
|||
### 语法
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
```
|
||||
|
||||
### 效果
|
||||
|
|
|
@ -61,7 +61,9 @@ To add an image, add an exclamation mark `!`, followed by alt text in brackets `
|
|||
### Syntax
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||
```
|
||||
|
||||
### Output
|
||||
|
@ -211,51 +213,3 @@ To create a code block, add three backticks ```` ``` ```` at the start and end o
|
|||
- Milk
|
||||
- Cheese
|
||||
```
|
||||
|
||||
#### Output
|
||||
|
||||
- Fruit
|
||||
- Apple
|
||||
- Orange
|
||||
- Banana
|
||||
- Dairy
|
||||
- Milk
|
||||
- Cheese
|
||||
|
||||
## Other Elements
|
||||
|
||||
Including `<sup>` superscript, `<sub>` subscript, `<abbr>` abbreviation, `<del>` strikethrough, `<u>` wavy underline, `<kbd>` keyboard input, and `<mark>` highlight.
|
||||
|
||||
### Syntax
|
||||
|
||||
```html
|
||||
H<sub>2</sub>O
|
||||
|
||||
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
|
||||
|
||||
<abbr title="Graphics Interchange Format">GIF</abbr> is a bitmap image format.
|
||||
|
||||
Good writers always check for <u title="spelling">speling</u> mistakes.
|
||||
|
||||
Press <kbd>CTRL</kbd> + <kbd>ALT</kbd> + <kbd>Delete</kbd> to end the session.
|
||||
|
||||
There is <del>nothing</del> no code either good or bad, but running it makes it so.
|
||||
|
||||
Most <mark>salamanders</mark> are nocturnal, and hunt for insects, worms, and other small creatures.
|
||||
```
|
||||
|
||||
### Output
|
||||
|
||||
H<sub>2</sub>O
|
||||
|
||||
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
|
||||
|
||||
<abbr title="Graphics Interchange Format">GIF</abbr> is a bitmap image format.
|
||||
|
||||
Good writers always check for <u title="spelling">speling</u> mistakes.
|
||||
|
||||
Press <kbd>CTRL</kbd> + <kbd>ALT</kbd> + <kbd>Delete</kbd> to end the session.
|
||||
|
||||
There is <del>nothing</del> no code either good or bad, but running it makes it so.
|
||||
|
||||
Most <mark>salamanders</mark> are nocturnal, and hunt for insects, worms, and other small creatures.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
title: Guía de Estilo Markdown
|
||||
published: 2025-03-08
|
||||
updated: 2025-03-23
|
||||
tags:
|
||||
tags:
|
||||
- Guía
|
||||
pin: 98
|
||||
toc: false
|
||||
|
@ -61,7 +61,9 @@ Para agregar una imagen, añada un signo de exclamación `!`, seguido de texto a
|
|||
### Sintaxis
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||
```
|
||||
|
||||
### Resultado
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
title: Markdown スタイルガイド
|
||||
published: 2025-03-08
|
||||
updated: 2025-03-23
|
||||
tags:
|
||||
tags:
|
||||
- ガイド
|
||||
pin: 98
|
||||
toc: false
|
||||
|
@ -61,7 +61,9 @@ abbrlink: markdown-style-guide
|
|||
### 構文
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||
```
|
||||
|
||||
### 効果
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
title: Руководство по стилю Markdown
|
||||
published: 2025-03-08
|
||||
updated: 2025-03-23
|
||||
tags:
|
||||
tags:
|
||||
- Руководство
|
||||
pin: 98
|
||||
toc: false
|
||||
|
@ -61,7 +61,9 @@ Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sap
|
|||
### Синтаксис
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||
```
|
||||
|
||||
### Результат
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
title: Markdown 樣式指南
|
||||
published: 2025-03-08
|
||||
updated: 2025-03-23
|
||||
tags:
|
||||
tags:
|
||||
- 指南
|
||||
pin: 98
|
||||
toc: false
|
||||
|
@ -61,7 +61,9 @@ abbrlink: markdown-style-guide
|
|||
### 語法
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||
```
|
||||
|
||||
### 效果
|
||||
|
|
|
@ -61,7 +61,9 @@ abbrlink: markdown-style-guide
|
|||
### 语法
|
||||
|
||||
```
|
||||

|
||||

|
||||
|
||||

|
||||
```
|
||||
|
||||
### 效果
|
||||
|
@ -258,4 +260,4 @@ X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
|
|||
|
||||
按下 <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>Delete</kbd> 以结束会话。
|
||||
|
||||
大多数<mark>蝾螈</mark>昼伏夜出,以昆虫、蠕虫等小生物为食。
|
||||
大多数<mark>蝾螈</mark>昼伏夜出,以昆虫、蠕虫等小生物为食。
|
||||
|
|
|
@ -86,6 +86,8 @@ global: {
|
|||
dateFormat: 'YYYY-MM-DD'
|
||||
// enable KaTeX for mathematical formulas rendering
|
||||
katex: true // true, false
|
||||
// enable table of contents for all posts by default
|
||||
toc: true // true, false
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -163,16 +165,16 @@ footer: {
|
|||
url: 'https://github.com/radishzzz/astro-theme-retypeset',
|
||||
},
|
||||
{
|
||||
name: 'X',
|
||||
url: 'https://x.com/radishzz_',
|
||||
},
|
||||
name: 'Email',
|
||||
url: 'email@radishzz.cc',
|
||||
}
|
||||
// {
|
||||
// name: 'Email',
|
||||
// url: 'https://example@gmail.com',
|
||||
// }
|
||||
// name: 'X',
|
||||
// url: 'https://x.com/radishzz_',
|
||||
// },
|
||||
]
|
||||
// year of website start
|
||||
startYear: 2024
|
||||
startYear: 2025
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -182,8 +184,6 @@ footer: {
|
|||
preload: {
|
||||
// link prefetch strategies
|
||||
linkPrefetch: 'viewport' // hover, tap, viewport, load
|
||||
// comment server url
|
||||
commentURL: 'https://retypeset-comment.radishzz.cc'
|
||||
// image hosting url
|
||||
imageHostURL: 'https://image.radishzz.cc'
|
||||
// custom google analytics js
|
||||
|
@ -236,7 +236,7 @@ const EXCERPT_LENGTHS: Record<ExcerptScene, {
|
|||
|
||||
### Open Graph
|
||||
|
||||
Open Graph social image styles.
|
||||
[Open Graph social card](https://orcascan.com/tools/open-graph-validator?url=https%3A%2F%2Fretypeset.radishzz.cc%2Fen%2Fposts%2Ftheme-guide%2F) styles.
|
||||
|
||||
```ts
|
||||
// src/pages/og/[...image].ts
|
||||
|
@ -265,7 +265,7 @@ getImageOptions: (_path, page) => ({
|
|||
|
||||
### RSS Feed
|
||||
|
||||
RSS feed page styles.
|
||||
[RSS feed page](https://retypeset.radishzz.cc/en/rss.xml) styles.
|
||||
|
||||
```html
|
||||
<!-- public/rss/rss-style.xsl -->
|
||||
|
@ -317,7 +317,7 @@ Pins the article to the top. The higher the number, the higher the priority of t
|
|||
|
||||
#### toc
|
||||
|
||||
Generate table of contents. Shows h2 to h4 headings. Default is true.
|
||||
Generate table of contents. Shows h2 to h4 headings. Uses the global `global.toc` configuration by default, but can be overridden individually in each article.
|
||||
|
||||
#### lang
|
||||
|
||||
|
|
|
@ -86,6 +86,8 @@ global: {
|
|||
dateFormat: 'YYYY-MM-DD'
|
||||
// habilitar KaTeX para renderizar fórmulas matemáticas
|
||||
katex: true // true, false
|
||||
// habilitar tabla de contenidos para todos los artículos por defecto
|
||||
toc: true // true, false
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -163,16 +165,16 @@ footer: {
|
|||
url: 'https://github.com/radishzzz/astro-theme-retypeset',
|
||||
},
|
||||
{
|
||||
name: 'X',
|
||||
url: 'https://x.com/radishzz_',
|
||||
},
|
||||
name: 'Email',
|
||||
url: 'email@radishzz.cc',
|
||||
}
|
||||
// {
|
||||
// name: 'Email',
|
||||
// url: 'https://example@gmail.com',
|
||||
// }
|
||||
// name: 'X',
|
||||
// url: 'https://x.com/radishzz_',
|
||||
// },
|
||||
]
|
||||
// año de inicio del sitio web
|
||||
startYear: 2024
|
||||
startYear: 2025
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -182,8 +184,6 @@ footer: {
|
|||
preload: {
|
||||
// estrategias de precarga de enlaces
|
||||
linkPrefetch: 'viewport' // hover, tap, viewport, load
|
||||
// URL del servidor de comentarios
|
||||
commentURL: 'https://retypeset-comment.radishzz.cc'
|
||||
// URL de alojamiento de imágenes
|
||||
imageHostURL: 'https://image.radishzz.cc'
|
||||
// js personalizado de google analytics
|
||||
|
@ -236,7 +236,7 @@ const EXCERPT_LENGTHS: Record<ExcerptScene, {
|
|||
|
||||
### Open Graph
|
||||
|
||||
Estilos de imágenes sociales Open Graph.
|
||||
Estilos de [tarjetas sociales Open Graph](https://orcascan.com/tools/open-graph-validator?url=https%3A%2F%2Fretypeset.radishzz.cc%2Fes%2Fposts%2Ftheme-guide%2F).
|
||||
|
||||
```ts
|
||||
// src/pages/og/[...image].ts
|
||||
|
@ -265,7 +265,7 @@ getImageOptions: (_path, page) => ({
|
|||
|
||||
### Canal RSS
|
||||
|
||||
Estilos de página del feed RSS.
|
||||
Estilos de [página del feed RSS](https://retypeset.radishzz.cc/es/rss.xml).
|
||||
|
||||
```html
|
||||
<!-- public/rss/rss-style.xsl -->
|
||||
|
@ -317,7 +317,7 @@ Fija el artículo en la parte superior. Cuanto mayor sea el número, mayor será
|
|||
|
||||
#### toc
|
||||
|
||||
Genera tabla de contenidos. Muestra encabezados h2 a h4. El valor predeterminado es true.
|
||||
Genera tabla de contenidos. Muestra encabezados de h2 a h4. Utiliza la configuración global `global.toc` por defecto, pero puede ser modificada individualmente en cada artículo.
|
||||
|
||||
#### lang
|
||||
|
||||
|
|
|
@ -86,6 +86,8 @@ global: {
|
|||
dateFormat: 'YYYY-MM-DD'
|
||||
// 数式表示のためのKaTeXを有効化
|
||||
katex: true // true, false
|
||||
// デフォルトですべての記事に目次を表示
|
||||
toc: true // true, false
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -163,16 +165,16 @@ footer: {
|
|||
url: 'https://github.com/radishzzz/astro-theme-retypeset',
|
||||
},
|
||||
{
|
||||
name: 'X',
|
||||
url: 'https://x.com/radishzz_',
|
||||
},
|
||||
name: 'Email',
|
||||
url: 'email@radishzz.cc',
|
||||
}
|
||||
// {
|
||||
// name: 'Email',
|
||||
// url: 'https://example@gmail.com',
|
||||
// }
|
||||
// name: 'X',
|
||||
// url: 'https://x.com/radishzz_',
|
||||
// },
|
||||
]
|
||||
// サイト開始年
|
||||
startYear: 2024
|
||||
startYear: 2025
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -182,8 +184,6 @@ footer: {
|
|||
preload: {
|
||||
// リンクプリフェッチ戦略
|
||||
linkPrefetch: 'viewport' // hover, tap, viewport, load
|
||||
// コメントサーバー URL
|
||||
commentURL: 'https://retypeset-comment.radishzz.cc'
|
||||
// 画像ホスティング URL
|
||||
imageHostURL: 'https://image.radishzz.cc'
|
||||
// カスタム Google Analytics JS
|
||||
|
@ -236,7 +236,7 @@ const EXCERPT_LENGTHS: Record<ExcerptScene, {
|
|||
|
||||
### Open Graph
|
||||
|
||||
Open Graphソーシャル画像スタイル。
|
||||
[Open Graphソーシャルカード](https://orcascan.com/tools/open-graph-validator?url=https%3A%2F%2Fretypeset.radishzz.cc%2Fja%2Fposts%2Ftheme-guide%2F)スタイル。
|
||||
|
||||
```ts
|
||||
// src/pages/og/[...image].ts
|
||||
|
@ -265,7 +265,7 @@ getImageOptions: (_path, page) => ({
|
|||
|
||||
### RSSフィード
|
||||
|
||||
RSSフィードページスタイル。
|
||||
[RSSフィードページ](https://retypeset.radishzz.cc/ja/rss.xml)スタイル。
|
||||
|
||||
```html
|
||||
<!-- public/rss/rss-style.xsl -->
|
||||
|
@ -317,7 +317,7 @@ abbrlink: theme-guide
|
|||
|
||||
#### toc
|
||||
|
||||
目次を自動生成するかどうか。h2からh4までの見出しを表示します。デフォルトは true。
|
||||
目次を生成するかどうか。h2からh4までの見出しを表示します。デフォルトではグローバル設定 `global.toc` を使用しますが、記事ごとに個別に設定することも可能です。
|
||||
|
||||
#### lang
|
||||
|
||||
|
|
|
@ -86,6 +86,8 @@ global: {
|
|||
dateFormat: 'YYYY-MM-DD'
|
||||
// включить KaTeX для отображения математических формул
|
||||
katex: true // true, false
|
||||
// включить оглавление для всех статей по умолчанию
|
||||
toc: true // true, false
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -163,16 +165,16 @@ footer: {
|
|||
url: 'https://github.com/radishzzz/astro-theme-retypeset',
|
||||
},
|
||||
{
|
||||
name: 'X',
|
||||
url: 'https://x.com/radishzz_',
|
||||
},
|
||||
name: 'Email',
|
||||
url: 'email@radishzz.cc',
|
||||
}
|
||||
// {
|
||||
// name: 'Email',
|
||||
// url: 'https://example@gmail.com',
|
||||
// }
|
||||
// name: 'X',
|
||||
// url: 'https://x.com/radishzz_',
|
||||
// },
|
||||
]
|
||||
// год начала работы веб-сайта
|
||||
startYear: 2024
|
||||
startYear: 2025
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -182,8 +184,6 @@ footer: {
|
|||
preload: {
|
||||
// стратегии предзагрузки ссылок
|
||||
linkPrefetch: 'viewport' // hover, tap, viewport, load
|
||||
// URL сервера комментариев
|
||||
commentURL: 'https://retypeset-comment.radishzz.cc'
|
||||
// URL хостинга изображений
|
||||
imageHostURL: 'https://image.radishzz.cc'
|
||||
// пользовательский скрипт Google Analytics
|
||||
|
@ -236,7 +236,7 @@ const EXCERPT_LENGTHS: Record<ExcerptScene, {
|
|||
|
||||
### Open Graph
|
||||
|
||||
Стили изображений Open Graph для социальных сетей.
|
||||
Стили [карточек Open Graph для социальных сетей](https://orcascan.com/tools/open-graph-validator?url=https%3A%2F%2Fretypeset.radishzz.cc%2Fru%2Fposts%2Ftheme-guide%2F).
|
||||
|
||||
```ts
|
||||
// src/pages/og/[...image].ts
|
||||
|
@ -265,7 +265,7 @@ getImageOptions: (_path, page) => ({
|
|||
|
||||
### RSS-лента
|
||||
|
||||
Стили страницы RSS-ленты.
|
||||
Стили [страницы RSS-ленты](https://retypeset.radishzz.cc/ru/rss.xml).
|
||||
|
||||
```html
|
||||
<!-- public/rss/rss-style.xsl -->
|
||||
|
@ -317,7 +317,7 @@ abbrlink: theme-guide
|
|||
|
||||
#### toc
|
||||
|
||||
Генерировать оглавление. Показывает заголовки от h2 до h4. По умолчанию — true.
|
||||
Генерировать оглавление. Показывает заголовки от h2 до h4. По умолчанию использует глобальный параметр `global.toc`, но может быть изменен индивидуально в каждой статье.
|
||||
|
||||
#### lang
|
||||
|
||||
|
|
|
@ -86,6 +86,8 @@ global: {
|
|||
dateFormat: 'YYYY-MM-DD'
|
||||
// 啟用 KaTeX 數學公式渲染
|
||||
katex: true // true, false
|
||||
// 預設為所有文章開啟目錄
|
||||
toc: true // true, false
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -163,16 +165,16 @@ footer: {
|
|||
url: 'https://github.com/radishzzz/astro-theme-retypeset',
|
||||
},
|
||||
{
|
||||
name: 'X',
|
||||
url: 'https://x.com/radishzz_',
|
||||
},
|
||||
name: 'Email',
|
||||
url: 'email@radishzz.cc',
|
||||
}
|
||||
// {
|
||||
// name: 'Email',
|
||||
// url: 'https://example@gmail.com',
|
||||
// }
|
||||
// name: 'X',
|
||||
// url: 'https://x.com/radishzz_',
|
||||
// },
|
||||
]
|
||||
// 建站年份
|
||||
startYear: 2024
|
||||
startYear: 2025
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -182,8 +184,6 @@ footer: {
|
|||
preload: {
|
||||
// 鏈接預加載策略
|
||||
linkPrefetch: 'viewport' // hover, tap, viewport, load
|
||||
// 評論服務器地址
|
||||
commentURL: 'https://retypeset-comment.radishzz.cc'
|
||||
// 圖床地址
|
||||
imageHostURL: 'https://image.radishzz.cc'
|
||||
// 定制 google analytics js
|
||||
|
@ -236,7 +236,7 @@ const EXCERPT_LENGTHS: Record<ExcerptScene, {
|
|||
|
||||
### Open Graph
|
||||
|
||||
Open Graph 社交圖片樣式。
|
||||
[Open Graph 社交卡片](https://orcascan.com/tools/open-graph-validator?url=https%3A%2F%2Fretypeset.radishzz.cc%2Fzh-tw%2Fposts%2Ftheme-guide%2F) 樣式。
|
||||
|
||||
```ts
|
||||
// src/pages/og/[...image].ts
|
||||
|
@ -265,7 +265,7 @@ getImageOptions: (_path, page) => ({
|
|||
|
||||
### RSS 訂閱
|
||||
|
||||
RSS 訂閱頁配色。
|
||||
[RSS 訂閱頁](https://retypeset.radishzz.cc/zh-tw/rss.xml) 配色。
|
||||
|
||||
```html
|
||||
<!-- public/rss/rss-style.xsl -->
|
||||
|
@ -317,7 +317,7 @@ abbrlink: theme-guide
|
|||
|
||||
#### toc
|
||||
|
||||
是否生成目錄。顯示 h2 至 h4 標題。預設為 true。
|
||||
是否生成目錄。顯示 h2 至 h4 標題。預設為全域配置 `global.toc` 的選項,可在文章中單獨設定以覆蓋全域配置。
|
||||
|
||||
#### lang
|
||||
|
||||
|
|
|
@ -86,6 +86,8 @@ global: {
|
|||
dateFormat: 'YYYY-MM-DD'
|
||||
// 启用 KaTeX 数学公式渲染
|
||||
katex: true // true, false
|
||||
// 默认为所有文章开启目录
|
||||
toc: true // true, false
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -163,16 +165,16 @@ footer: {
|
|||
url: 'https://github.com/radishzzz/astro-theme-retypeset',
|
||||
},
|
||||
{
|
||||
name: 'X',
|
||||
url: 'https://x.com/radishzz_',
|
||||
},
|
||||
name: 'Email',
|
||||
url: 'email@radishzz.cc',
|
||||
}
|
||||
// {
|
||||
// name: 'Email',
|
||||
// url: 'https://example@gmail.com',
|
||||
// }
|
||||
// name: 'X',
|
||||
// url: 'https://x.com/radishzz_',
|
||||
// },
|
||||
]
|
||||
// 建站年份
|
||||
startYear: 2024
|
||||
startYear: 2025
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -182,8 +184,6 @@ footer: {
|
|||
preload: {
|
||||
// 链接预加载策略
|
||||
linkPrefetch: 'viewport' // hover, tap, viewport, load
|
||||
// 评论服务器地址
|
||||
commentURL: 'https://retypeset-comment.radishzz.cc'
|
||||
// 图床地址
|
||||
imageHostURL: 'https://image.radishzz.cc'
|
||||
// 定制 google analytics js
|
||||
|
@ -236,7 +236,7 @@ const EXCERPT_LENGTHS: Record<ExcerptScene, {
|
|||
|
||||
### Open Graph
|
||||
|
||||
Open Graph 社交图片样式。
|
||||
[Open Graph 社交卡片](https://orcascan.com/tools/open-graph-validator?url=https%3A%2F%2Fretypeset.radishzz.cc%2Fposts%2Ftheme-guide%2F) 样式。
|
||||
|
||||
```ts
|
||||
// src/pages/og/[...image].ts
|
||||
|
@ -265,7 +265,7 @@ getImageOptions: (_path, page) => ({
|
|||
|
||||
### RSS 订阅
|
||||
|
||||
RSS 订阅页配色。
|
||||
[RSS 订阅页](https://retypeset.radishzz.cc/rss.xml) 配色。
|
||||
|
||||
```html
|
||||
<!-- public/rss/rss-style.xsl -->
|
||||
|
@ -317,7 +317,7 @@ abbrlink: theme-guide
|
|||
|
||||
#### toc
|
||||
|
||||
是否生成目录。显示 h2 至 h4 标题。默认为 true。
|
||||
是否生成目录。显示 h2 至 h4 标题。默认为全局配置 `global.toc` 的选项,可在文章中单独设置以覆盖全局配置。
|
||||
|
||||
#### lang
|
||||
|
||||
|
|
|
@ -18,10 +18,11 @@ const langCode = currentLang === defaultLocale ? '' : `${currentLang}/`
|
|||
|
||||
const { title, subtitle, description, author, url, favicon, i18nTitle } = themeConfig.site
|
||||
const { mode, light: { background: lightMode }, dark: { background: darkMode } } = themeConfig.color
|
||||
const { katex } = themeConfig.global
|
||||
const { katex: katexEnabled } = themeConfig.global
|
||||
const { enabled: commentEnabled = false, waline: { serverURL: walineServerURL = '' } = {} } = themeConfig.comment ?? {}
|
||||
const { verification = {}, twitterID = '', googleAnalyticsID = '', umamiAnalyticsID = '', apiflashKey = '' } = themeConfig.seo ?? {}
|
||||
const { google = '', bing = '', yandex = '', baidu = '' } = verification
|
||||
const { commentURL = '', customGoogleAnalyticsJS = '', customUmamiAnalyticsJS = '' } = themeConfig.preload
|
||||
const { customGoogleAnalyticsJS = '', customUmamiAnalyticsJS = '' } = themeConfig.preload
|
||||
|
||||
const initMetaTheme = mode === 'dark' ? darkMode : lightMode
|
||||
const siteTitle = i18nTitle ? currentUI.title : title
|
||||
|
@ -54,9 +55,9 @@ const pageImage = postSlug
|
|||
<link rel="preload" href="/fonts/EarlySummer-Subset.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="/fonts/Snell-Black.woff2" as="font" type="font/woff2" crossorigin />
|
||||
<link rel="preload" href="/fonts/Snell-Bold.woff2" as="font" type="font/woff2" crossorigin />
|
||||
{katex && <link rel="stylesheet" href={katexCSS} />}
|
||||
{commentURL && <link rel="preconnect" href={commentURL} crossorigin />}
|
||||
{commentURL && <link rel="dns-prefetch" href={commentURL} />}
|
||||
<link rel="preload" href="/fonts/STIX-Italic.woff2" as="font" type="font/woff2" crossorigin />
|
||||
{commentEnabled && walineServerURL && <link rel="stylesheet" href="/assets/waline/waline.css" />}
|
||||
{katexEnabled && <link rel="stylesheet" href={katexCSS} />}
|
||||
<link rel="alternate" href="/rss.xml" type="application/rss+xml" title="RSS Feed" />
|
||||
<link rel="alternate" href="/atom.xml" type="application/atom+xml" title="Atom Feed" />
|
||||
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||
|
@ -111,7 +112,7 @@ function isCurrentDark() {
|
|||
function initTheme(doc = document) {
|
||||
const isDark = isCurrentDark()
|
||||
doc.documentElement.classList.toggle('dark', isDark)
|
||||
const metaTheme = doc.querySelector('meta[name="theme-color"]')
|
||||
const metaTheme = doc.head.querySelector('meta[name="theme-color"]')
|
||||
if (metaTheme) {
|
||||
metaTheme.setAttribute('content', isDark ? darkMode : lightMode)
|
||||
}
|
||||
|
|
|
@ -4,15 +4,16 @@ import Footer from '@/components/Footer.astro'
|
|||
import Header from '@/components/Header.astro'
|
||||
import Navbar from '@/components/Navbar.astro'
|
||||
import GithubCard from '@/components/Widgets/GithubCard.astro'
|
||||
import GsapAnimation from '@/components/Widgets/GsapAnimation.astro'
|
||||
import PhotoSwipe from '@/components/Widgets/PhotoSwipe.astro'
|
||||
import Scrollbar from '@/components/Widgets/Scrollbar.astro'
|
||||
import themeConfig from '@/config'
|
||||
import Head from '@/layouts/Head.astro'
|
||||
import { getPageInfo } from '@/utils/page'
|
||||
import '@/styles/global.css'
|
||||
import '@/styles/font.css'
|
||||
import '@/styles/heti.css'
|
||||
import '@/styles/extend.css'
|
||||
import '@/styles/font.css'
|
||||
import '@/styles/global.css'
|
||||
import '@/styles/markdown.css'
|
||||
import '@/styles/transition.css'
|
||||
|
||||
interface Props {
|
||||
postTitle?: string
|
||||
|
@ -25,22 +26,20 @@ const { postTitle, postDescription, postSlug, supportedLangs = [] } = Astro.prop
|
|||
const { isPost } = getPageInfo(Astro.url.pathname)
|
||||
const fontStyle = themeConfig.global.fontStyle === 'serif' ? 'font-serif' : 'font-sans'
|
||||
const MarginBottom = isPost && themeConfig.comment?.enabled
|
||||
? 'mb-10' // Post page with comment system
|
||||
: 'mb-12' // Other pages without comment system
|
||||
? 'mb-10' // Post page with comments
|
||||
: 'mb-12' // Other pages without comments
|
||||
---
|
||||
|
||||
<html
|
||||
lang={Astro.currentLocale}
|
||||
class:list={[fontStyle, { 'scroll-smooth': isPost }]}
|
||||
data-overlayscrollbars-initialize
|
||||
>
|
||||
<Head {postTitle} {postDescription} {postSlug} />
|
||||
<body data-overlayscrollbars-initialize>
|
||||
|
||||
<body>
|
||||
<div
|
||||
class="mx-auto max-w-205.848 min-h-vh w-full min-h-dvh"
|
||||
p="x-[min(7.25vw,3.731rem)] y-9"
|
||||
lg="p-0 min-h-full max-w-[min(calc(75vw-16rem),44rem)] mx-[max(5.625rem,calc(50vw-34.375rem))] my-20"
|
||||
lg="mx-[max(5rem,calc(50vw-35rem))] my-20 max-w-[min(calc(75vw-16rem),44rem)] min-h-full p-0"
|
||||
>
|
||||
<Header />
|
||||
<Navbar />
|
||||
|
@ -49,8 +48,8 @@ const MarginBottom = isPost && themeConfig.comment?.enabled
|
|||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
<GsapAnimation />
|
||||
<Button supportedLangs={supportedLangs} />
|
||||
<Scrollbar />
|
||||
<GithubCard />
|
||||
<PhotoSwipe />
|
||||
</body>
|
||||
|
|
|
@ -6,8 +6,15 @@ import Layout from '@/layouts/Layout.astro'
|
|||
<!-- Decorative Line -->
|
||||
<div class="uno-decorative-line"></div>
|
||||
<!-- Page Not Found -->
|
||||
<h3 class="mt--1.3 text-8 text-primary font-bold leading-1.2em font-navbar lg:text-9">PAGE<br>NOT<br>FOUND</h3>
|
||||
<p class="mt-3.6 text-3.6 leading-1.4em font-navbar lg:(mt-4 text-4)">It looks like the page you're looking for<br>does not exist or has been moved.</p>
|
||||
<h3 class="mt--1.3 flex flex-col text-8 text-primary font-bold leading-1.2em font-navbar lg:text-9">
|
||||
<span>PAGE</span>
|
||||
<span>NOT</span>
|
||||
<span>FOUND</span>
|
||||
</h3>
|
||||
<p class="mt-3.6 flex flex-col text-3.6 leading-1.4em font-navbar lg:(mt-4 text-4)">
|
||||
<span>It looks like the page you're looking for</span>
|
||||
<span>does not exist or has been moved.</span>
|
||||
</p>
|
||||
<!-- Unused Div -->
|
||||
<div class=""></div>
|
||||
</Layout>
|
||||
|
|
|
@ -3,7 +3,7 @@ import type { CollectionEntry } from 'astro:content'
|
|||
import { getCollection, render } from 'astro:content'
|
||||
import Comments from '@/components/Comments/index.astro'
|
||||
import PostDate from '@/components/PostDate.astro'
|
||||
import GoBack from '@/components/Widgets/GoBack.astro'
|
||||
import BackButton from '@/components/Widgets/BackButton.astro'
|
||||
import TOC from '@/components/Widgets/TOC.astro'
|
||||
import { allLocales, defaultLocale, moreLocales } from '@/config'
|
||||
import { getTagPath } from '@/i18n/path'
|
||||
|
@ -109,12 +109,12 @@ const { Content, headings, remarkPluginFrontmatter } = await render(post)
|
|||
<article class="heti mb-12.6">
|
||||
<div class="relative">
|
||||
<!-- Go Back Button On Desktop -->
|
||||
<GoBack />
|
||||
<BackButton />
|
||||
<!-- Title -->
|
||||
<h1 class="post-title">
|
||||
<span
|
||||
transition:name={`post-${post.data.abbrlink || post.id}-${lang}`}
|
||||
data-disable-transition-on-theme
|
||||
data-disable-theme-transition
|
||||
>
|
||||
{post.data.title}
|
||||
</span>
|
||||
|
@ -123,9 +123,10 @@ const { Content, headings, remarkPluginFrontmatter } = await render(post)
|
|||
|
||||
<!-- Date -->
|
||||
<div
|
||||
id="gsap-post-page-date"
|
||||
class="mb-16.3 block c-primary font-time"
|
||||
transition:name={`time-${post.data.abbrlink || post.id}-${lang}`}
|
||||
data-disable-transition-on-theme
|
||||
data-disable-theme-transition
|
||||
>
|
||||
<PostDate
|
||||
date={post.data.published}
|
||||
|
@ -136,21 +137,25 @@ const { Content, headings, remarkPluginFrontmatter } = await render(post)
|
|||
<!-- TOC -->
|
||||
{post.data.toc && <TOC headings={headings} />}
|
||||
<!-- Content -->
|
||||
<Content />
|
||||
<div id="gsap-post-page-content">
|
||||
<Content />
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Tags -->
|
||||
{post.data.tags && post.data.tags.length > 0 && (
|
||||
<div class="uno-decorative-line"></div>
|
||||
<div class="uno-tags-wrapper">
|
||||
{post.data.tags.map((tag: string) => (
|
||||
<a
|
||||
href={getTagPath(tag, lang)}
|
||||
class="uno-tags-style"
|
||||
>
|
||||
{tag}
|
||||
</a>
|
||||
))}
|
||||
<div id="gsap-post-page-tags">
|
||||
<div class="uno-decorative-line"></div>
|
||||
<div class="uno-tags-wrapper">
|
||||
{post.data.tags.map((tag: string) => (
|
||||
<a
|
||||
href={getTagPath(tag, lang)}
|
||||
class="uno-tags-style"
|
||||
>
|
||||
{tag}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<!-- Comments -->
|
||||
|
|
|
@ -52,7 +52,7 @@ const supportedLangs = await getTagSupportedLangs(tag)
|
|||
href={getTagPath(tagName, lang)}
|
||||
class={`uno-tags-style ${
|
||||
tag === tagName
|
||||
? 'border-secondary/75 text-primary'
|
||||
? 'border-secondary/80 text-primary'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
|
|
23
src/plugins/rehype-unwrap-img.mjs
Normal file
23
src/plugins/rehype-unwrap-img.mjs
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { visit } from 'unist-util-visit'
|
||||
|
||||
export function rehypeUnwrapImg() {
|
||||
return (tree) => {
|
||||
visit(tree, 'element', (node, index, parent) => {
|
||||
if (
|
||||
node.tagName === 'p'
|
||||
&& node.children
|
||||
&& parent
|
||||
&& node.children.every(child =>
|
||||
child.tagName === 'img'
|
||||
|| (child.type === 'text' && child.value.trim() === ''),
|
||||
)
|
||||
) {
|
||||
|
||||
const imgNodes = node.children.filter(child => child.tagName === 'img')
|
||||
if (imgNodes.length > 0) {
|
||||
parent.children.splice(index, 1, ...imgNodes)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,28 +1,47 @@
|
|||
/* KaTeX Overflow Fix */
|
||||
.katex-display {
|
||||
--at-apply: 'overflow-x-auto overflow-y-hidden scrollbar-hidden';
|
||||
}
|
||||
.katex-display::-webkit-scrollbar {
|
||||
display: none;
|
||||
/* GitHub Card */
|
||||
.gc-container {
|
||||
--at-apply: 'block mb-4 px-5 py-4 overflow-x-auto uno-round-border bg-secondary/5';
|
||||
--at-apply: 'transition-colors ease-out lg:(px-6 py-5) hover:(bg-secondary/10 c-primary)';
|
||||
scrollbar-color: oklch(var(--un-preset-theme-colors-secondary) / 0.15) transparent;
|
||||
}
|
||||
|
||||
/* Heading Anchor Link */
|
||||
.heading-anchor-link {
|
||||
--at-apply: 'inline-block translate-y-0.1em c-secondary/0';
|
||||
/* Title Bar */
|
||||
.gc-title-bar {
|
||||
--at-apply: 'flex items-center gap-2.5 lg:gap-3';
|
||||
}
|
||||
h1:hover .heading-anchor-link,
|
||||
h2:hover .heading-anchor-link,
|
||||
h3:hover .heading-anchor-link,
|
||||
h4:hover .heading-anchor-link {
|
||||
--at-apply: 'c-secondary/40';
|
||||
.gc-owner-avatar {
|
||||
--at-apply: 'flex-shrink-0 w-5.5 aspect-square rounded-full bg-secondary/20';
|
||||
}
|
||||
.heading-anchor-link svg {
|
||||
--at-apply: 'ml-0.4em aspect-square w-0.9em transition-colors active:scale-90 hover:c-secondary/80';
|
||||
.gc-repo-title {
|
||||
--at-apply: 'flex items-center leading-normal lg:text-lg';
|
||||
}
|
||||
.gc-slash {
|
||||
--at-apply: 'mx-1 op-40 lg:mx-1.2';
|
||||
}
|
||||
.gc-github-icon {
|
||||
--at-apply: 'flex-shrink-0 ml-auto w-5.5 lg:w-6';
|
||||
}
|
||||
|
||||
/* Video */
|
||||
iframe {
|
||||
--at-apply: 'mb-4 w-full aspect-video';
|
||||
/* Repo Description */
|
||||
.gc-repo-description.gc-repo-description {
|
||||
--at-apply: 'mt-2.45 mb-3.5 text-sm text-start lg:(mt-2.8 mb-4 text-base)';
|
||||
}
|
||||
|
||||
/* Info Bar */
|
||||
.gc-info-bar {
|
||||
--at-apply: 'flex items-center gap-1.75 text-xs lg:(gap-2 text-sm)';
|
||||
}
|
||||
.gc-info-icon {
|
||||
--at-apply: 'flex-shrink-0';
|
||||
}
|
||||
.gc-stars-count {
|
||||
--at-apply: 'mr-3 lg:mr-4';
|
||||
}
|
||||
.gc-forks-count {
|
||||
--at-apply: 'mr-3.75 lg:mr-5';
|
||||
}
|
||||
.gc-license-info {
|
||||
--at-apply: 'ml-0.5 mr-4';
|
||||
}
|
||||
|
||||
/* Admonition >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
||||
|
@ -93,55 +112,12 @@ iframe {
|
|||
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4.47.22A.749.749 0 0 1 5 0h6c.199 0 .389.079.53.22l4.25 4.25c.141.14.22.331.22.53v6a.749.749 0 0 1-.22.53l-4.25 4.25A.749.749 0 0 1 11 16H5a.749.749 0 0 1-.53-.22L.22 11.53A.749.749 0 0 1 0 11V5c0-.199.079-.389.22-.53Zm.84 1.28L1.5 5.31v5.38l3.81 3.81h5.38l3.81-3.81V5.31L10.69 1.5ZM8 4a.75.75 0 0 1 .75.75v3.5a.75.75 0 0 1-1.5 0v-3.5A.75.75 0 0 1 8 4Zm0 8a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z'%3E%3C/path%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
/* GitHub Card >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
||||
.gc-container {
|
||||
--at-apply: 'block mb-4 px-5 py-4 overflow-x-auto uno-round-border bg-secondary/5 scrollbar-hidden';
|
||||
--at-apply: 'transition-colors lg:(px-6 py-5) hover:(bg-secondary/10 c-primary)';
|
||||
}
|
||||
.gc-container::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Title Bar */
|
||||
.gc-title-bar {
|
||||
--at-apply: 'flex items-center gap-2.5 lg:gap-3';
|
||||
}
|
||||
.gc-owner-avatar {
|
||||
--at-apply: 'flex-shrink-0 w-5.5 aspect-square rounded-full bg-secondary/20';
|
||||
}
|
||||
.gc-repo-title {
|
||||
--at-apply: 'flex items-center leading-normal lg:text-lg';
|
||||
}
|
||||
.gc-slash {
|
||||
--at-apply: 'mx-1 op-40 lg:mx-1.2';
|
||||
}
|
||||
.gc-github-icon {
|
||||
--at-apply: 'flex-shrink-0 ml-auto w-5.5 lg:w-6';
|
||||
}
|
||||
|
||||
/* Repo Description */
|
||||
.gc-repo-description.gc-repo-description {
|
||||
--at-apply: 'mt-2.45 mb-3.5 text-sm text-start lg:(mt-2.8 mb-4 text-base)';
|
||||
}
|
||||
|
||||
/* Info Bar */
|
||||
.gc-info-bar {
|
||||
--at-apply: 'flex items-center gap-1.75 text-xs lg:(gap-2 text-sm)';
|
||||
}
|
||||
.gc-info-icon {
|
||||
--at-apply: 'flex-shrink-0';
|
||||
}
|
||||
.gc-stars-count {
|
||||
--at-apply: 'mr-3 lg:mr-4';
|
||||
}
|
||||
.gc-forks-count {
|
||||
--at-apply: 'mr-3.75 lg:mr-5';
|
||||
}
|
||||
.gc-license-info {
|
||||
--at-apply: 'ml-0.5 mr-4';
|
||||
}
|
||||
|
||||
/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
||||
/* Video */
|
||||
/* iframe {
|
||||
--at-apply: 'mb-4 w-full aspect-video';
|
||||
} */
|
||||
|
||||
/* :where(details) {
|
||||
--at-apply: 'my-4 px-4 py-3 border border-solid border-secondary/25 rounded cursor-pointer';
|
||||
}
|
||||
|
|
|
@ -1,3 +1,41 @@
|
|||
/* Snell Roundhand Static Font */
|
||||
@font-face {
|
||||
font-family: "Snell-Bold";
|
||||
src: url("/fonts/Snell-Bold.woff2") format("woff2");
|
||||
font-display: swap;
|
||||
unicode-range: U+0030-0039,U+0041-005A,U+0061-007A,U+00C1,U+00C9,U+00CD,U+00D3,U+00DA,U+00DC,U+00D1,U+00E1,U+00E9,U+00ED,U+00F3,U+00FA,U+00FC,U+00F1,U+0410-044F,U+0401,U+0451,U+0021-002F,U+003A-0040,U+00A9;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Snell-Black";
|
||||
src: url("/fonts/Snell-Black.woff2") format("woff2");
|
||||
font-display: swap;
|
||||
unicode-range: U+0030-0039,U+0041-005A,U+0061-007A,U+00C1,U+00C9,U+00CD,U+00D3,U+00DA,U+00DC,U+00D1,U+00E1,U+00E9,U+00ED,U+00F3,U+00FA,U+00FC,U+00F1,U+0410-044F,U+0401,U+0451,U+0021-002F,U+003A-0040,U+00A9;
|
||||
}
|
||||
|
||||
/* STIXTwoText Variable Font */
|
||||
@font-face {
|
||||
font-family: "STIX";
|
||||
src: url("/fonts/STIX.woff2") format("woff2-variations");
|
||||
font-display: swap;
|
||||
font-weight: 400 700;
|
||||
unicode-range: U+0030-0039,U+0041-005A,U+0061-007A,U+00C1,U+00C9,U+00CD,U+00D3,U+00DA,U+00DC,U+00D1,U+00E1,U+00E9,U+00ED,U+00F3,U+00FA,U+00FC,U+00F1,U+0410-044F,U+0401,U+0451,U+0021-002F,U+003A-0040,U+00A9;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "STIX-Italic";
|
||||
src: url("/fonts/STIX-Italic.woff2") format("woff2-variations");
|
||||
font-display: swap;
|
||||
font-weight: 400 700;
|
||||
unicode-range: U+0030-0039,U+0041-005A,U+0061-007A,U+00C1,U+00C9,U+00CD,U+00D3,U+00DA,U+00DC,U+00D1,U+00E1,U+00E9,U+00ED,U+00F3,U+00FA,U+00FC,U+00F1,U+0410-044F,U+0401,U+0451,U+0021-002F,U+003A-0040,U+00A9;
|
||||
}
|
||||
|
||||
/* Minimal Subset of EarlySummerSerif Variable Font */
|
||||
@font-face {
|
||||
font-family: "EarlySummer-Subset";
|
||||
src: url("/fonts/EarlySummer-Subset.woff2") format("woff2-variations");
|
||||
font-display: swap;
|
||||
font-weight: 400 700;
|
||||
}
|
||||
|
||||
/* EarlySummerSerif Variable Font */
|
||||
@font-face {font-family:"EarlySummer";src:url("/fonts/EarlySummer-Split/264097d8d9da16491b480a1c46afe035.woff2") format("woff2-variations");font-display: swap;font-weight: 400 700;unicode-range:U+B7,U+9F2C,U+9F3B,U+9F3E,U+9F84,U+9F99,U+9F9F;}
|
||||
@font-face {font-family:"EarlySummer";src:url("/fonts/EarlySummer-Split/c0df1afa44c13da520351e6aa9be3d9a.woff2") format("woff2-variations");font-display: swap;font-weight: 400 700;unicode-range:U+9711,U+9784,U+97A6,U+97C1,U+97C6,U+982C,U+983C,U+9854-9855,U+98B1,U+98B3,U+98BA,U+9935,U+993D,U+9951,U+99C4-99C6,U+9A12-9A13,U+9AEA,U+9AEE,U+9B06,U+9B0D,U+9B1A,U+9B28,U+9D12,U+9E78,U+9EB5,U+9EBA,U+9ED2,U+9ED9,U+9F07,U+9F15,U+9F62-9F63,U+FF01,U+FF08-FF09,U+FF0C,U+FF1A-FF1B,U+FF1F;}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
}
|
||||
html {
|
||||
--at-apply: 'bg-background c-secondary antialiased';
|
||||
}
|
||||
::selection {
|
||||
--at-apply: 'bg-mark';
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: oklch(var(--un-preset-theme-colors-secondary) / 0.25) transparent;
|
||||
scrollbar-gutter: stable both-edges;
|
||||
}
|
||||
|
||||
/* Fix Flash Issue On iOS */
|
||||
|
@ -15,6 +15,37 @@ body {
|
|||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
}
|
||||
body::selection {
|
||||
--at-apply: 'bg-highlight';
|
||||
}
|
||||
|
||||
/* Fix KaTeX Overflow Issue */
|
||||
.katex-display {
|
||||
--at-apply: 'overflow-x-auto overflow-y-hidden scrollbar-hidden';
|
||||
}
|
||||
.katex-display::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Heading Anchor Link */
|
||||
.heading-anchor-link {
|
||||
--at-apply: 'inline-block translate-y-0.1em';
|
||||
}
|
||||
h1:hover .heading-anchor-link svg,
|
||||
h2:hover .heading-anchor-link svg,
|
||||
h3:hover .heading-anchor-link svg,
|
||||
h4:hover .heading-anchor-link svg {
|
||||
--at-apply: 'op-80';
|
||||
}
|
||||
.heading-anchor-link svg {
|
||||
--at-apply: 'ml-0.4em aspect-square w-0.9em op-0 transition-opacity ease-out active:scale-90';
|
||||
}
|
||||
h1:hover .heading-anchor-link svg:hover,
|
||||
h2:hover .heading-anchor-link svg:hover,
|
||||
h3:hover .heading-anchor-link svg:hover,
|
||||
h4:hover .heading-anchor-link svg:hover {
|
||||
--at-apply: 'op-80';
|
||||
}
|
||||
|
||||
/* Highlight Hover Animation */
|
||||
.highlight-static,
|
||||
|
@ -23,85 +54,22 @@ body {
|
|||
}
|
||||
.highlight-static::after,
|
||||
.highlight-hover::after {
|
||||
--at-apply: 'content-[""] absolute bottom-0.5em left-0 z--1 h-0.5em w-full bg-mark';
|
||||
--at-apply: 'content-[""] absolute left-0 z--1 h-0.5em w-full bg-highlight';
|
||||
}
|
||||
.highlight-static::after,
|
||||
.highlight-hover:hover::after {
|
||||
--at-apply: 'origin-bottom-left scale-x-100';
|
||||
}
|
||||
.highlight-hover::after {
|
||||
--at-apply: 'origin-bottom-right scale-x-0 transition-transform duration-300 ease-out';
|
||||
--at-apply: 'origin-bottom-right scale-x-0 transition-transform ease-out lg:duration-225';
|
||||
}
|
||||
|
||||
/* View Transition with Theme Toggle >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
||||
::view-transition-new(theme-transition) {
|
||||
animation: reveal 1s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
clip-path: inset(0 0 0 0);
|
||||
z-index: 99;
|
||||
}
|
||||
::view-transition-old(theme-transition) {
|
||||
animation: none;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes reveal {
|
||||
from {
|
||||
clip-path: inset(var(--from));
|
||||
/* Fix Highlight Position Issue on iOS */
|
||||
@supports (-webkit-touch-callout: none) {
|
||||
.navbar-highlight-position-fix {
|
||||
--at-apply: 'after:bottom-0.68em';
|
||||
}
|
||||
.footer-highlight-position-fix {
|
||||
--at-apply: 'after:bottom-0.39em';
|
||||
}
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--from: 0 0 100% 0;
|
||||
}
|
||||
html:not(.dark) {
|
||||
--from: 100% 0 0 0;
|
||||
}
|
||||
|
||||
/* Disable animations for other elements during theme switching */
|
||||
html[data-theme-transition] [data-disable-transition-on-theme] {
|
||||
view-transition-name: none !important;
|
||||
}
|
||||
|
||||
/* Fallback animation when view-transition-name is not supported */
|
||||
@supports not (view-transition-name: none) {
|
||||
html:not([data-restore-theme]) {
|
||||
--at-apply: 'transition-colors duration-300 ease-out';
|
||||
}
|
||||
}
|
||||
|
||||
/* Snell Roundhand Static Font >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
||||
@font-face {
|
||||
font-family: "Snell-Bold";
|
||||
src: url("/fonts/Snell-Bold.woff2") format("woff2");
|
||||
font-display: swap;
|
||||
unicode-range: U+0030-0039,U+0041-005A,U+0061-007A,U+00C1,U+00C9,U+00CD,U+00D3,U+00DA,U+00DC,U+00D1,U+00E1,U+00E9,U+00ED,U+00F3,U+00FA,U+00FC,U+00F1,U+0410-044F,U+0401,U+0451,U+0021-002F,U+003A-0040,U+00A9;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Snell-Black";
|
||||
src: url("/fonts/Snell-Black.woff2") format("woff2");
|
||||
font-display: swap;
|
||||
unicode-range: U+0030-0039,U+0041-005A,U+0061-007A,U+00C1,U+00C9,U+00CD,U+00D3,U+00DA,U+00DC,U+00D1,U+00E1,U+00E9,U+00ED,U+00F3,U+00FA,U+00FC,U+00F1,U+0410-044F,U+0401,U+0451,U+0021-002F,U+003A-0040,U+00A9;
|
||||
}
|
||||
|
||||
/* STIXTwoText Variable Font */
|
||||
@font-face {
|
||||
font-family: "STIX";
|
||||
src: url("/fonts/STIX.woff2") format("woff2-variations");
|
||||
font-display: swap;
|
||||
font-weight: 400 700;
|
||||
unicode-range: U+0030-0039,U+0041-005A,U+0061-007A,U+00C1,U+00C9,U+00CD,U+00D3,U+00DA,U+00DC,U+00D1,U+00E1,U+00E9,U+00ED,U+00F3,U+00FA,U+00FC,U+00F1,U+0410-044F,U+0401,U+0451,U+0021-002F,U+003A-0040,U+00A9;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "STIX-Italic";
|
||||
src: url("/fonts/STIX-Italic.woff2") format("woff2-variations");
|
||||
font-display: swap;
|
||||
font-weight: 400 700;
|
||||
unicode-range: U+0030-0039,U+0041-005A,U+0061-007A,U+00C1,U+00C9,U+00CD,U+00D3,U+00DA,U+00DC,U+00D1,U+00E1,U+00E9,U+00ED,U+00F3,U+00FA,U+00FC,U+00F1,U+0410-044F,U+0401,U+0451,U+0021-002F,U+003A-0040,U+00A9;
|
||||
}
|
||||
|
||||
/* Minimal Subset of EarlySummerSerif Variable Font */
|
||||
@font-face {
|
||||
font-family: "EarlySummer-Subset";
|
||||
src: url("/fonts/EarlySummer-Subset.woff2") format("woff2-variations");
|
||||
font-display: swap;
|
||||
font-weight: 400 700;
|
||||
}
|
||||
|
|
|
@ -7,52 +7,41 @@
|
|||
|
||||
/* Global Styles */
|
||||
.heti {
|
||||
--at-apply: 'break-words leading-1.5em hyphens-auto cjk:tracking-0.02em';
|
||||
--at-apply: 'break-words leading-normal hyphens-auto cjk:tracking-0.02em';
|
||||
}
|
||||
|
||||
/* Customized Post Title */
|
||||
.heti .post-title {
|
||||
--at-apply: 'mb-2 text-8.6 c-primary font-bold leading-12 lg:text-9';
|
||||
--at-apply: 'mb-2 text-8.6 font-bold lg:text-9';
|
||||
}
|
||||
|
||||
/* Headings */
|
||||
.heti :where(h1),
|
||||
.heti :where(h2),
|
||||
.heti :where(h3),
|
||||
.heti :where(h4),
|
||||
.heti :where(h5),
|
||||
.heti :where(h6) {
|
||||
--at-apply: 'mb-3 mt-6 font-semibold';
|
||||
.heti :where(h1, h2, h3, h4, h5, h6) {
|
||||
--at-apply: 'mb-4 font-semibold';
|
||||
}
|
||||
.heti :where(h1, h2, h3) {
|
||||
--at-apply: 'text-balance leading-1.33em cjk:text-pretty cjk:tracking-0.05em';
|
||||
}
|
||||
.heti :where(h1) {
|
||||
--at-apply: 'text-7 leading-12';
|
||||
--at-apply: 'mt-9.6 text-7 text-primary';
|
||||
}
|
||||
.heti :where(h2) {
|
||||
--at-apply: 'text-6 leading-9';
|
||||
--at-apply: 'mt-9.6 text-6 text-primary';
|
||||
}
|
||||
.heti :where(h3) {
|
||||
--at-apply: 'text-5 leading-9';
|
||||
--at-apply: 'mt-6.5 text-5';
|
||||
}
|
||||
.heti :where(h4) {
|
||||
--at-apply: 'text-4.5 leading-6';
|
||||
--at-apply: 'mt-6 text-4.5';
|
||||
}
|
||||
.heti :where(h5) {
|
||||
--at-apply: 'text-4 leading-6';
|
||||
--at-apply: 'mt-6 text-4';
|
||||
}
|
||||
.heti :where(h6) {
|
||||
--at-apply: 'text-3.5 leading-6';
|
||||
--at-apply: 'mt-6 font-normal';
|
||||
}
|
||||
.heti :where(h1),
|
||||
.heti :where(h2),
|
||||
.heti :where(h3) {
|
||||
--at-apply: 'text-balance cjk:text-pretty cjk:tracking-0.05em';
|
||||
}
|
||||
.heti :where(h1 + h2),
|
||||
.heti :where(h2 + h3),
|
||||
.heti :where(h3 + h4),
|
||||
.heti :where(h4 + h5),
|
||||
.heti :where(h5 + h6) {
|
||||
--at-apply: 'mt-3';
|
||||
.heti :where(h1 + h2, h2 + h3, h3 + h4, h4 + h5, h5 + h6) {
|
||||
--at-apply: 'mt-4';
|
||||
}
|
||||
|
||||
/* Paragraphs */
|
||||
|
@ -62,26 +51,33 @@
|
|||
|
||||
/* Links */
|
||||
.heti :where(a:not(.gc-container)) {
|
||||
--at-apply: 'break-all font-medium tracking-0 underline underline-0.075em decoration-secondary/40 underline-offset-0.2em';
|
||||
--at-apply: 'transition-colors hover:(c-primary decoration-secondary/80) lg:underline-0.1em';
|
||||
--at-apply: 'break-all font-semibold tracking-0 underline underline-0.075em decoration-secondary/80 underline-offset-0.1em';
|
||||
--at-apply: 'transition-colors ease-out hover:(c-primary decoration-primary/80) lg:underline-0.1em';
|
||||
}
|
||||
|
||||
/* Images */
|
||||
.heti :where(img) {
|
||||
--at-apply: 'mx-auto cursor-zoom-in';
|
||||
transform: translateZ(0);
|
||||
-webkit-transform: translateZ(0);
|
||||
--at-apply: 'mb-4 mx-auto cursor-zoom-in';
|
||||
}
|
||||
.heti :where(figure) {
|
||||
--at-apply: 'mx-auto mb-4';
|
||||
}
|
||||
.heti figure img {
|
||||
--at-apply: 'mb-0';
|
||||
}
|
||||
.heti :where(figcaption) {
|
||||
--at-apply: 'mt-2 text-center text-sm text-secondary/80';
|
||||
--at-apply: 'mt-3 text-center text-sm text-secondary/80';
|
||||
}
|
||||
|
||||
/* Code Blocks */
|
||||
.heti :where(pre) {
|
||||
--at-apply: 'mb-4 overflow-auto uno-round-border px-4 py-3 bg-secondary/5!';
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: oklch(var(--un-preset-theme-colors-secondary) / 0) transparent;
|
||||
transition: scrollbar-color 0.3s ease-out;
|
||||
}
|
||||
.heti :where(pre:hover) {
|
||||
scrollbar-color: oklch(var(--un-preset-theme-colors-secondary) / 0.15) transparent;
|
||||
}
|
||||
.heti pre :where(code) {
|
||||
--at-apply: 'border-none bg-transparent p-0';
|
||||
|
@ -124,10 +120,13 @@ html.dark .heti pre :where(span) {
|
|||
|
||||
/* Tables */
|
||||
.heti :where(table) {
|
||||
--at-apply: 'mb-4 box-border block max-w-full table-fixed overflow-x-auto scrollbar-hidden';
|
||||
--at-apply: 'mb-4 box-border block max-w-full table-fixed overflow-x-auto';
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: oklch(var(--un-preset-theme-colors-secondary) / 0) transparent;
|
||||
transition: scrollbar-color 0.3s ease-out;
|
||||
}
|
||||
.heti :where(table)::-webkit-scrollbar {
|
||||
--at-apply: 'hidden';
|
||||
.heti :where(table:hover) {
|
||||
scrollbar-color: oklch(var(--un-preset-theme-colors-secondary) / 0.15) transparent;
|
||||
}
|
||||
.heti :where(th),
|
||||
.heti :where(td) {
|
||||
|
@ -182,7 +181,7 @@ html.dark .heti pre :where(span) {
|
|||
/* Superscript and Subscript >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
||||
.heti :where(sub),
|
||||
.heti :where(sup) {
|
||||
--at-apply: 'relative mx-0.1em align-baseline text-0.75em leading-1';
|
||||
--at-apply: 'relative mx-0.1em align-baseline text-0.75em';
|
||||
}
|
||||
.heti :where(sub) {
|
||||
--at-apply: 'bottom--0.25em';
|
||||
|
@ -212,7 +211,7 @@ html.dark .heti :where(u) {
|
|||
|
||||
/* Highlighted Text */
|
||||
.heti :where(mark) {
|
||||
--at-apply: 'bg-mark py-0.65 text-inherit';
|
||||
--at-apply: 'bg-highlight py-0.65 text-inherit';
|
||||
}
|
||||
|
||||
/* Footnotes */
|
||||
|
@ -222,7 +221,7 @@ html.dark .heti :where(u) {
|
|||
}
|
||||
.heti sup:target,
|
||||
.heti sup a:target {
|
||||
--at-apply: 'bg-mark';
|
||||
--at-apply: 'bg-highlight';
|
||||
}
|
||||
.heti .data-footnote-backref {
|
||||
--at-apply: 'font-serif no-underline';
|
||||
|
@ -253,4 +252,3 @@ html.dark .heti :where(u) {
|
|||
.heti :where(q:is(:lang(zh), :lang(ja), :lang(ko))) {
|
||||
quotes: "「" "」" "『" "』";
|
||||
}
|
||||
|
34
src/styles/transition.css
Normal file
34
src/styles/transition.css
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* View Transition */
|
||||
::view-transition-new(animation-theme-toggle) {
|
||||
animation: reveal 0.8s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
clip-path: inset(0 0 0 0);
|
||||
z-index: 99;
|
||||
}
|
||||
::view-transition-old(animation-theme-toggle) {
|
||||
animation: none;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes reveal {
|
||||
from {
|
||||
clip-path: inset(var(--from));
|
||||
}
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--from: 0 0 100% 0;
|
||||
}
|
||||
html:not(.dark) {
|
||||
--from: 100% 0 0 0;
|
||||
}
|
||||
|
||||
/* Disable animations for special elements during theme switching */
|
||||
html[data-theme-changing] [data-disable-theme-transition] {
|
||||
view-transition-name: none !important;
|
||||
}
|
||||
|
||||
/* Fallback animation when view-transition-name is not supported */
|
||||
@supports not (view-transition-name: none) {
|
||||
html {
|
||||
--at-apply: 'transition-colors duration-300 ease-out';
|
||||
}
|
||||
}
|
2
src/types/index.d.ts
vendored
2
src/types/index.d.ts
vendored
|
@ -34,6 +34,7 @@ export interface ThemeConfig {
|
|||
fontStyle: 'sans' | 'serif'
|
||||
dateFormat: 'YYYY-MM-DD' | 'MM-DD-YYYY' | 'DD-MM-YYYY' | 'MONTH DAY YYYY' | 'DAY MONTH YYYY'
|
||||
katex: boolean
|
||||
toc: boolean
|
||||
}
|
||||
|
||||
comment: {
|
||||
|
@ -73,7 +74,6 @@ export interface ThemeConfig {
|
|||
|
||||
preload: {
|
||||
linkPrefetch: 'hover' | 'tap' | 'viewport' | 'load'
|
||||
commentURL?: string
|
||||
imageHostURL?: string
|
||||
customGoogleAnalyticsJS?: string
|
||||
customUmamiAnalyticsJS?: string
|
||||
|
|
|
@ -54,7 +54,7 @@ const getOptimizedImageUrl = memoize(async (srcPath: string, baseUrl: string) =>
|
|||
*/
|
||||
async function fixRelativeImagePaths(htmlContent: string, baseUrl: string): Promise<string> {
|
||||
const htmlDoc = htmlParser(htmlContent)
|
||||
const images = htmlDoc.querySelectorAll('img')
|
||||
const images = htmlDoc.getElementsByTagName('img')
|
||||
const imagePromises = []
|
||||
|
||||
for (const img of images) {
|
||||
|
|
|
@ -20,7 +20,7 @@ export default defineConfig({
|
|||
dark: {
|
||||
colors: {
|
||||
...dark,
|
||||
mark: 'oklch(0.93 0.195089 103.2532 / 0.2)', // rgba(255,235,0,0.5)
|
||||
highlight: 'oklch(0.93 0.195089 103.2532 / 0.2)', // rgba(255,235,0,0.5)
|
||||
note: 'oklch(70.7% 0.165 254.624 / 0.8)', // blue-400
|
||||
tip: 'oklch(76.5% 0.177 163.223 / 0.8)', // emerald-400
|
||||
important: 'oklch(71.4% 0.203 305.504 / 0.8)', // purple-400
|
||||
|
@ -34,7 +34,7 @@ export default defineConfig({
|
|||
theme: {
|
||||
colors: {
|
||||
...light,
|
||||
mark: 'oklch(0.93 0.195089 103.2532 / 0.5)', // rgba(255,235,0,0.5)
|
||||
highlight: 'oklch(0.93 0.195089 103.2532 / 0.5)', // rgba(255,235,0,0.5)
|
||||
note: 'oklch(48.8% 0.243 264.376 / 0.8)', // blue-700
|
||||
tip: 'oklch(50.8% 0.118 165.612 / 0.8)', // emerald-700
|
||||
important: 'oklch(49.6% 0.265 301.924 / 0.8)', // purple-700
|
||||
|
@ -55,11 +55,11 @@ export default defineConfig({
|
|||
}],
|
||||
],
|
||||
shortcuts: {
|
||||
'uno-desktop-column': 'fixed w-14rem right-[max(5.625rem,calc(50vw-34.375rem))]',
|
||||
'uno-tags-style': 'inline-block whitespace-nowrap border border-secondary/25 rounded-full px-3.2 py-0.7 c-secondary transition-colors hover:(border-secondary/75 text-primary)',
|
||||
'uno-decorative-line': 'h-0.25 w-10 bg-secondary/25 mb-4.5 lg:(w-11 mb-6)',
|
||||
'uno-desktop-column': 'fixed right-[max(5rem,calc(50vw-35rem))] w-14rem',
|
||||
'uno-tags-style': 'inline-block whitespace-nowrap border border-secondary/25 rounded-full px-3.2 py-0.7 c-secondary transition-colors ease-out hover:(border-secondary/80 text-primary)',
|
||||
'uno-decorative-line': 'mb-4.5 h-0.25 w-10 bg-secondary/25 lg:(mb-6 w-11)',
|
||||
'uno-tags-wrapper': 'flex flex-wrap gap-x-3 gap-y-3.2',
|
||||
'uno-round-border': 'rounded border border-solid border-secondary/5',
|
||||
'uno-round-border': 'border border-secondary/5 rounded border-solid',
|
||||
},
|
||||
variants: [
|
||||
(matcher) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue