Merge branch 'master' into giscus

This commit is contained in:
radishzzz 2025-05-29 20:35:59 +01:00
commit 4b270755bf
356 changed files with 21152 additions and 3604 deletions

View file

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M2.6 21.4c2 2 5.9 2.9 8.9 0l3.5-3.5-1-1-3.5 3.5c-1.4 1.4-4.2 1.9-6.4-.3s-1.8-5-.3-6.4l3.5-3.5-1-1-3.5 3.5c-3 3-2 6.9 0 8.9ZM21.4 2.6c2 2 2.9 5.9 0 8.9L17.9 15l-1-1 3.5-3.5c1.4-1.4 1.9-4.2-.3-6.4s-5-1.8-6.4-.3l-3.5 3.5-1-1 3.5-3.5c3-3 6.9-2 8.9 0Z"/>
<path d="m8.01 14.97 6.93-6.93 1.061 1.06-6.93 6.93z"/>
</svg>

After

Width:  |  Height:  |  Size: 386 B

View file

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M6.9.8v18h14.5V.8zm12.8 16h-11v-14h11z"/>
<path d="M4.3 21.2V5.6l-1.7.5v17.1h14.3l.6-2z"/>
</svg>

After

Width:  |  Height:  |  Size: 171 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="m23.1 6.4-1.3-1.3L9.4 16.6l-6.3-5.4-1.2 1.2L9.4 20z"/>
</svg>

After

Width:  |  Height:  |  Size: 133 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M17.8.7L4,12l13.8,11.4.7-.9L7.2,12,18.5,1.5l-.7-.8Z"/>
</svg>

After

Width:  |  Height:  |  Size: 133 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M19.1 21 12.4 2h-1.2L4.6 21l-2.5.2v.8h6.3v-.8L5.6 21l2-5.9h7.5l2 5.9-3.3.2v.8h8.1v-.8zM7.9 14.3l3.4-10.1 3.5 10.1z"/>
</svg>

After

Width:  |  Height:  |  Size: 196 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M23.7,8.1l-2.2-2.2-3.3-3.3L15.9.3C9,6.4,6.5,7,.4,7.5l6.4,6.4,1,1-6.5,6.9.9.9,6.9-6.5,1,1,6.4,6.4c.5-6.1,1.1-8.6,7.2-15.5ZM7.9,12.7l-4.4-4.4c4.1-.5,5.9-1,12-6l1.4,1.4,3.3,3.3,1.4,1.4c-5,6.1-5.5,7.9-6,12l-4.4-4.4-3.3-3.3Z"/>
</svg>

After

Width:  |  Height:  |  Size: 301 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M12,.5C5.6.5.4,5.6.4,12s5.1,11.5,11.6,11.5,11.5-5.1,11.5-11.5S18.4.5,12,.5M12,21.5C5.9,21.5,1,17.3,1,12S5.9,2.6,12,2.6s11,4.2,11,9.5-4.9,9.4-11,9.4"/>
</svg>

After

Width:  |  Height:  |  Size: 229 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M22.2 2.3H1.8V4h19.9zM22.2 20H1.8v1.7h19.9zM15.5 11.2H1.8v1.6H15z"/>
</svg>

After

Width:  |  Height:  |  Size: 147 B

View file

@ -1,4 +1,6 @@
---
import LanguageSwitcherIcon from '@/assets/icons/language-switcher.svg'
import ThemeToggleIcon from '@/assets/icons/theme-toggle.svg'
import { moreLocales, themeConfig } from '@/config'
import { getNextGlobalLangPath, getNextSupportedLangPath } from '@/i18n/path'
import { isPostPage, isTagPage } from '@/utils/page'
@ -7,7 +9,10 @@ interface Props {
supportedLangs: string[]
}
const { light: { background: lightMode }, dark: { background: darkMode } } = themeConfig.color
const {
light: { background: lightMode },
dark: { background: darkMode },
} = themeConfig.color
const { supportedLangs } = Astro.props
const currentPath = Astro.url.pathname
@ -20,15 +25,14 @@ const showLanguageSwitcher = moreLocales.length > 0
const useSupportedLangs = isPost || (isTag && supportedLangs.length > 0)
// Choose a language switch list according to the page type
const nextUrl = useSupportedLangs
? getNextSupportedLangPath(currentPath, supportedLangs) // Switch between supported languages
: getNextGlobalLangPath(currentPath) // Switch between all languages
? getNextSupportedLangPath(currentPath, supportedLangs) // Switch between supported languages in post/tag page
: getNextGlobalLangPath(currentPath) // Switch between all languages in other pages
---
<div
class:list={[
'absolute flex gap-6 top-14.6 right-7.25vw 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))])',
'absolute right-7.25vw top-14.6 flex gap-6 min-[823px]:max-[1024px]:right-[calc(50vw-22rem)]',
'lg:(fixed bottom-48 right-[max(5rem,calc(50vw-35rem))] top-auto w-14rem)',
]}
>
<!-- Language Switcher -->
@ -38,36 +42,31 @@ const nextUrl = useSupportedLangs
class="aspect-square w-4 c-secondary active:scale-90 hover:c-primary"
aria-label="Switch website language"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
<LanguageSwitcherIcon
aria-hidden="true"
class="h-full w-full"
fill="currentColor"
>
<path d="M19.1 21 12.4 2h-1.2L4.6 21l-2.5.2v.8h6.3v-.8L5.6 21l2-5.9h7.5l2 5.9-3.3.2v.8h8.1v-.8zM7.9 14.3l3.4-10.1 3.5 10.1z" />
</svg>
/>
</a>
)}
<!-- Theme Toggle -->
<button
id="theme-toggle-button"
aria-label="Switch light/dark theme"
class="button-theme-toggle aspect-square w-4.2 c-secondary active:scale-90 hover:c-primary"
class="aspect-square w-4 c-secondary active:scale-90 hover:c-primary"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
<ThemeToggleIcon
aria-hidden="true"
fill="currentColor"
>
<path d="M12 1C5.9 1 1 5.9 1 12s4.9 11 11 11 11-4.9 11-11S18.1 1 12 1m0 20c-5.8 0-10.5-4-10.5-9S6.2 3 12 3s10.5 4 10.5 9-4.7 9-10.5 9" />
</svg>
/>
</button>
</div>
<!-- Theme Toggle Script >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
<script is:inline define:vars={{ lightMode, darkMode }}>
<script
is:inline
define:vars={{ lightMode, darkMode }}
>
// Update theme
function updateTheme() {
// Toggle website theme
@ -76,7 +75,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)
}
@ -89,29 +88,29 @@ 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', () => {
// If browser doesn't support View Transitions API, update theme directly
if (!document.startViewTransition) {
const themeToggleButton = document.getElementById('theme-toggle-button')
// Add click listener to the button
if (themeToggleButton) {
themeToggleButton.addEventListener('click', () => {
// If reduceMotion is enabled or browser doesn't support View Transitions API, update theme directly
if (document.documentElement.classList.contains('reduce-motion') || !document.startViewTransition) {
updateTheme()
return
}
// 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)

View file

@ -2,66 +2,56 @@
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
const pathLang = Object.keys(walineLocaleMap).find(code =>
currentPath.startsWith(`/${code}/`),
)
// Return found path language or default language
const lang = pathLang || defaultLocale
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'
<!-- Waline Script >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
<script
is:inline
define:vars={{
serverURL,
emoji,
search,
imageUploader,
walineLocaleMap,
defaultLocale,
}}
type="module"
>
import { init } from '/vendors/waline/waline.js'
function initWaline() {
const walineEl = document.getElementById('waline')
const walineConfig = JSON.parse(walineEl?.dataset.config || '{}')
const currentPath = window.location.pathname
const pathLang = Object.keys(walineLocaleMap).find(code =>
currentPath.startsWith(`/${code}/`),
)
const lang = pathLang || defaultLocale
const currentWalineLang = walineLocaleMap[lang]
init({
el: '#waline',
path: window.location.pathname.replace(/^\/([a-z]{2}(-[a-z]{2})?)\//, '/'),
serverURL,
path: window.location.pathname.replace(/^\/([a-z]{2}(-[a-z]{2})?)\//, '/'), // Share comments on posts in different languages
lang: currentWalineLang,
emoji,
dark: 'html.dark',
requiredMeta: ['nick', 'mail'],
highlighter: false,
texRenderer: false,
imageUploader,
search,
noCopyright: true,
reaction: [],
...walineConfig,
})
}
initWaline()
document.addEventListener('astro:after-swap', initWaline)
document.addEventListener('astro:page-load', initWaline)
</script>
<!-- Custom CSS Styles >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
@ -69,141 +59,123 @@ document.addEventListener('astro:after-swap', initWaline)
#waline .wl-login-info {
--at-apply: 'mt-0 mr-3'
}
#waline .wl-avatar {
--at-apply: 'border-none'
}
#waline .wl-logout-btn {
--at-apply: 'z-99'
}
#waline .wl-login-nick:not(:has(img)) {
--at-apply: 'leading-3.6 mt-1.4';
}
#waline .wl-panel {
--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';
}
#waline .wl-header input {
--at-apply: 'text-2.8';
}
#waline .wl-card,
#waline .wl-header.item3 {
--at-apply: 'border-b-0';
}
#waline .wl-card .wl-quote {
--at-apply: 'border-is-none mt-6';
--at-apply: 'border-is-none mt-4';
}
#waline .wl-editor {
--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-text-number,
#waline .wl-action[title="Markdown Guide"],
#waline .wl-sort,
#waline .wl-emoji-popup .wl-tab-wrapper::-webkit-scrollbar,
#waline .wl-gallery::-webkit-scrollbar {
--at-apply: 'hidden';
}
#waline .wl-emoji-popup {
--at-apply: 'start-0 border-secondary/25';
--at-apply: 'start-0 border-secondary/25 max-w-532px';
}
#waline .wl-emoji-popup .wl-tab-wrapper,
#waline .wl-gallery {
--at-apply: 'scrollbar-hidden';
#waline .wl-emoji-popup .wl-tab-wrapper {
scrollbar-width: thin;
}
#waline .wl-gif-popup {
--at-apply: 'border-secondary/25';
}
#waline .wl-gif-popup input {
--at-apply: 'bg-background border-secondary/25';
}
#waline .wl-gif-popup input::placeholder {
--at-apply: 'c-secondary/30 text-3.5';
}
#waline .wl-gallery {
--at-apply: 'scrollbar-hidden';
}
#waline .wl-meta-head {
--at-apply: 'pt-3 pb-2 px-0';
}
#waline .wl-card-item {
--at-apply: 'px-0';
}
#waline .wl-user-avatar {
--at-apply: 'mt-1';
}
#waline .wl-content p {
--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 {
--at-apply: 'mr-0.4';
}
#waline .wl-like {
--at-apply: 'mr-1.2';
}
</style>
<!-- Official CSS Variables >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
<!-- https://waline.js.org/reference/client/style.html -->
<style>
#waline {
/* Regular Colors */
--waline-white: var(--uno-colors-background);
--waline-light-grey: oklch(var(--un-preset-theme-colors-primary) / 0.25);
--waline-dark-grey: var(--uno-colors-secondary);
#waline {
/* Regular Colors */
--waline-white: oklch(var(--un-preset-theme-colors-background));
--waline-light-grey: oklch(var(--un-preset-theme-colors-primary) / 0.25);
--waline-dark-grey: oklch(var(--un-preset-theme-colors-secondary));
/* Theme Colors */
--waline-theme-color: var(--uno-colors-primary);
--waline-active-color: var(--uno-colors-primary);
/* Theme Colors */
--waline-theme-color: oklch(var(--un-preset-theme-colors-primary));
--waline-active-color: oklch(var(--un-preset-theme-colors-primary));
/* Layout Colors */
--waline-color: var(--uno-colors-secondary);
--waline-bg-color: var(--uno-colors-background);
--waline-bg-color-light: var(--uno-colors-background);
--waline-bg-color-hover: var(--uno-colors-background);
--waline-border-color: oklch(var(--un-preset-theme-colors-primary) / 0.25);
--waline-disable-bg-color: oklch(var(--un-preset-theme-colors-secondary) / 0.05);
--waline-disable-color: var(--uno-colors-primary);
/* Layout Colors */
--waline-color: oklch(var(--un-preset-theme-colors-secondary));
--waline-bg-color: oklch(var(--un-preset-theme-colors-background));
--waline-bg-color-light: oklch(var(--un-preset-theme-colors-background));
--waline-bg-color-hover: oklch(var(--un-preset-theme-colors-background));
--waline-border-color: oklch(var(--un-preset-theme-colors-primary) / 0.25);
--waline-disable-bg-color: oklch(var(--un-preset-theme-colors-secondary) / 0.05);
--waline-disable-color: oklch(var(--un-preset-theme-colors-primary));
/* Special Colors */
--waline-bq-color: oklch(var(--un-preset-theme-colors-primary) / 0.25);
/* Special Colors */
--waline-bq-color: oklch(var(--un-preset-theme-colors-primary) / 0.25);
/* Information */
--waline-info-bg-color: var(--uno-colors-background);
--waline-info-color: oklch(var(--un-preset-theme-colors-primary) / 0.25);
/* Information */
--waline-info-bg-color: oklch(var(--un-preset-theme-colors-background));
--waline-info-color: oklch(var(--un-preset-theme-colors-primary) / 0.25);
/* Rendering Options */
--waline-avatar-radius: 0.5rem;
}
</style>
/* Rendering Options */
--waline-avatar-radius: 0.5rem;
}
</style>

View file

@ -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 py-0.8 transition-colors after:bottom-0.35em hover:c-primary'
---
<footer
class="text-3 leading-4.75 font-navbar lg:text-3.5"
class="text-3 leading-1.25em font-navbar lg:text-3.5"
lg="uno-desktop-column bottom-20"
>
<p>
{links.map((link, index) => (
<>
<a class="transition-colors hover:c-primary" href={link.url}>
{link.name}
</a>
{index < links.length - 1 && ' / '}
<a class={footerLinkClass} href={link.url} target="_blank" rel="noopener noreferrer">{link.name}</a>&nbsp;{index < links.length - 1 && '/'}
</>
))}
</p>
<p>
Powered by <a class="transition-colors hover:c-primary" href="https://astro.build/">Astro</a> and <a class="transition-colors hover:c-primary" href="https://github.com/radishzzz/astro-theme-retypeset">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>

View file

@ -5,24 +5,11 @@ import { getPageInfo } from '@/utils/page'
const { currentLang, getLocalizedPath, isPost } = getPageInfo(Astro.url.pathname)
const { title, subtitle, i18nTitle } = themeConfig.site
const { titleGap } = themeConfig.global
const currentUI = ui[currentLang as keyof typeof ui]
const headerTitle = i18nTitle ? currentUI.title : title
const headerSubtitle = i18nTitle ? currentUI.subtitle : subtitle
const marginBottom = {
1: 'mb-0.9',
2: 'mb-1.8',
3: 'mb-2.7',
}[titleGap] || 'mb-1.8 '
const postMarginBottom = {
1: 'mb-1.9 lg:mb-0.9',
2: 'mb-2.8 lg:mb-1.8',
3: 'mb-3.7 lg:mb-2.7',
}[titleGap] || 'mb-2.8 lg:mb-1.8'
const TitleTag = isPost ? 'h2' : 'h1'
const SubtitleTag = isPost ? 'div' : 'h2'
---
@ -30,14 +17,14 @@ const SubtitleTag = isPost ? 'div' : 'h2'
<header
class:list={[
isPost ? 'mb-10.8' : 'mb-10.5',
'lg:(uno-desktop-column top-20)',
'lg:(uno-desktop-column top-20) cjk:tracking-0.02em',
]}
>
<TitleTag
class:list={[
isPost
? `${postMarginBottom} mt-3.2 text-5.375 c-secondary lg:(mt-0 text-9 c-primary)`
: `${marginBottom} text-8 w-75% c-primary lg:(text-9 w-full)`,
? `mb-2.8 mt-3 text-5.375 c-secondary lg:(mb-1.8 mt-0 text-9 c-primary)`
: `mb-1.8 w-75% text-8 c-primary lg:(w-full text-9)`,
'font-bold font-title',
]}
>
@ -45,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"
@ -60,9 +47,9 @@ const SubtitleTag = isPost ? 'div' : 'h2'
<SubtitleTag
class:list={[
isPost
? `opacity-0 lg:opacity-100`
? `op-0 lg:op-100`
: 'w-75% lg:w-full',
'c-secondary font-navbar text-3.5 lg:text-4',
'text-3.5 c-secondary font-navbar lg:text-4',
]}
aria-hidden={isPost}
>

View file

@ -10,7 +10,9 @@ const isTagActive = isTag
const isAboutActive = isAbout
function getNavItemClass(isActive: boolean) {
return isActive ? 'font-bold c-primary' : 'hover:(c-primary font-bold) transition-all'
return isActive
? 'highlight-static c-primary font-bold after:bottom-0.7em'
: 'highlight-hover transition-colors transition-font-weight after:bottom-0.7em 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)',
'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>

View file

@ -21,19 +21,19 @@ function formatDate(date: Date, format: 'YYYY-MM-DD' | 'MM-DD-YYYY' | 'DD-MM-YYY
}
switch (format) {
// ISO format: 2024-03-04
// ISO format: 2025-04-13
case 'YYYY-MM-DD':
return date.toISOString().split('T')[0]
// US date format: 03-04-2024
// US date format: 04-13-2025
case 'MM-DD-YYYY':
return date.toLocaleDateString('en-US', options).replace(/\//g, '-')
// European date format: 04-03-2024
// European date format: 13-04-2025
case 'DD-MM-YYYY':
return date.toLocaleDateString('en-GB', options).replace(/\//g, '-')
// US month text format: Mar 4 2024
// US month text format: Apr 13 2025
case 'MONTH DAY YYYY':
return date.toLocaleDateString('en-US', {
year: 'numeric',
@ -41,7 +41,7 @@ function formatDate(date: Date, format: 'YYYY-MM-DD' | 'MM-DD-YYYY' | 'DD-MM-YYY
day: 'numeric',
}).replace(',', '')
// British month text format: 4 Mar 2024
// British month text format: 13 Apr 2025
case 'DAY MONTH YYYY':
return date.toLocaleDateString('en-GB', {
year: 'numeric',

View file

@ -1,9 +1,10 @@
---
import type { CollectionEntry } from 'astro:content'
import PinIcon from '@/assets/icons/pin-icon.svg'
import PostDate from '@/components/PostDate.astro'
import { defaultLocale } from '@/config'
import { generateDescription } from '@/utils/description'
import { isTagPage } from '@/utils/page'
import { isHomePage } from '@/utils/page'
type Post = CollectionEntry<'posts'> & {
remarkPluginFrontmatter: {
@ -12,7 +13,7 @@ type Post = CollectionEntry<'posts'> & {
}
const { posts, lang, pinned = false } = Astro.props
const isTag = isTagPage(Astro.url.pathname)
const isHome = isHomePage(Astro.url.pathname)
export interface Props {
posts: Post[]
@ -32,40 +33,36 @@ function getPostPath(post: Post) {
{posts.map(post => (
<li
class="mb-5.5"
lg={isTag ? '' : 'mb-10'}
lg={isHome ? 'mb-10' : ''}
>
{/* post title */}
<h3 class="inline">
<h3 class="inline transition-colors hover:c-primary">
<a
class="hover:c-primary"
lg={isTag ? '' : 'font-medium text-4.5'}
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>
{/* pinned icon */}
{pinned && (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
<PinIcon
aria-hidden="true"
class="ml-1 inline-block aspect-square w-3.7 shrink-0 translate-y--0.45 lg:(ml-1.2 w-4.1)"
class="ml-0.25em inline-block aspect-square w-0.98em translate-y--0.1em lg:(w-1.05em translate-y--0.15em)"
fill="currentColor"
>
<path d="M16.5 23.6c.6-6.1 1.1-8.6 7.2-15.5L15.9.4C9 6.5 6.5 7 .4 7.5l7.4 7.4-6.4 7 .7.7 7-6.4zm-.8-21.3 6 6c-5 6.1-5.7 8.1-6.2 12.2L3.4 8.5C7.5 8 9.5 7.3 15.6 2.3Z" />
</svg>
/>
)}
</h3>
{/* 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}
@ -74,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,10 +79,10 @@ function getPostPath(post: Post) {
</div>
{/* desktop post description */}
{!isTag && (
{isHome && (
<div
class="heti hidden"
lg="mt-2 block"
lg="mt-2.25 block"
>
<p>{generateDescription(post, 'list')}</p>
</div>

View file

@ -0,0 +1,37 @@
---
import GoBackIcon from '@/assets/icons/go-back.svg';
---
<button
id="back-button"
class="hidden"
lg="absolute left--10 top-3.8 block aspect-square w-4.5 c-secondary/40 transition-colors ease-out hover:c-secondary/80 active:scale-90!"
aria-label="Go back"
>
<GoBackIcon
aria-hidden="true"
fill="currentColor"
/>
</button>
<!-- Go Back Script >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
<script>
function setupBackButton() {
document.getElementById('back-button')?.addEventListener('click', () => {
// Navigate back if history exists
if (window.history.length > 1) {
window.history.back()
}
else {
// Fallback to homepage
const siteTitleLink = document.getElementById('site-title-link')
if (siteTitleLink) {
siteTitleLink.click()
}
}
})
}
setupBackButton()
document.addEventListener('astro:after-swap', setupBackButton)
</script>

View file

@ -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"
@ -36,10 +36,10 @@ function initBackToTop() {
observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
backToTopButton?.classList.add('opacity-0', 'pointer-events-none', 'translate-y-4')
backToTopButton?.classList.add('op-0', 'pointer-events-none', 'translate-y-4')
}
else {
backToTopButton?.classList.remove('opacity-0', 'pointer-events-none', 'translate-y-4')
backToTopButton?.classList.remove('op-0', 'pointer-events-none', 'translate-y-4')
}
},
{
@ -60,18 +60,6 @@ function initBackToTop() {
})
}
function cleanup() {
// Cleanup observer
if (observer) {
observer.disconnect()
observer = null
}
// Remove event listeners
backToTopButton = null
}
// Handle page transitions
document.addEventListener('astro:page-load', initBackToTop)
document.addEventListener('astro:before-swap', cleanup)
document.addEventListener('astro:after-swap', initBackToTop)
</script>

View file

@ -0,0 +1,77 @@
<script>
const copyIcons = {
copy:
`<svg
viewBox="0 0 24 24"
fill="currentColor"
>
<path d="M6.9.8v18h14.5V.8zm12.8 16h-11v-14h11z"/>
<path d="M4.3 21.2V5.6l-1.7.5v17.1h14.3l.6-2z"/>
</svg>`,
success:
`<svg
viewBox="0 0 24 24"
fill="currentColor"
>
<path d="m23.1 6.4-1.3-1.3L9.4 16.6l-6.3-5.4-1.2 1.2L9.4 20z"/>
</svg>`,
}
// Track timeout references for each button to manage icon state transitions
const activeTimeouts = new WeakMap<HTMLButtonElement, ReturnType<typeof setTimeout>>()
async function handleCopy(button: HTMLButtonElement) {
const codeElement = button.parentElement?.querySelector('pre code')
const code = codeElement?.textContent || ''
try {
await navigator.clipboard.writeText(code)
// Clear existing timeout to prevent icon state conflicts on multiple clicks
const existingTimeout = activeTimeouts.get(button)
if (existingTimeout) {
clearTimeout(existingTimeout)
}
button.innerHTML = copyIcons.success
button.classList.add('copy-success')
// Set timeout to revert to copy icon after 1.5s
const timeoutId = setTimeout(() => {
button.innerHTML = copyIcons.copy
button.classList.remove('copy-success')
activeTimeouts.delete(button)
}, 1500)
activeTimeouts.set(button, timeoutId)
}
catch {
}
}
// Initialize copy buttons with icons and mark them to prevent duplicate initialization
function setupCodeCopyButtons() {
document
.querySelectorAll<HTMLButtonElement>('.code-copy-button:not([data-initialized])')
.forEach((button) => {
button.innerHTML = copyIcons.copy
button.setAttribute('data-initialized', 'true')
})
}
// Use event delegation for better performance
document.addEventListener('click', (e) => {
if (!(e.target instanceof HTMLElement))
return
// Find closest button element if clicked on button or child element
const button = e.target.closest('.code-copy-button') as HTMLButtonElement | null
if (button) {
handleCopy(button)
}
}, { passive: true })
setupCodeCopyButtons()
document.addEventListener('astro:page-load', setupCodeCopyButtons)
</script>

View file

@ -0,0 +1,71 @@
<script>
function setupGithubCards() {
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) {
loadCardData(entry.target as HTMLElement)
observer.unobserve(entry.target)
}
})
}, { rootMargin: '500px' })
Array.from(githubCards).forEach(card => observer.observe(card))
}
async function loadCardData(card: HTMLElement) {
const repo = card.dataset.repo
if (!repo)
return
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}`)
if (response.ok) {
const data = await response.json()
if (avatarEl && data.owner?.avatar_url)
avatarEl.style.backgroundImage = `url(${data.owner.avatar_url})`
if (descEl && data.description)
descEl.textContent = data.description
if (starsEl) {
starsEl.textContent = new Intl.NumberFormat('en', {
notation: 'compact',
maximumFractionDigits: 1,
}).format(data.stargazers_count)
}
if (forksEl) {
forksEl.textContent = new Intl.NumberFormat('en', {
notation: 'compact',
maximumFractionDigits: 1,
}).format(data.forks_count)
}
if (licenseEl)
licenseEl.textContent = data.license?.spdx_id || 'No License'
}
else {
if (descEl)
descEl.textContent = 'Loading failed.'
}
}
catch {
console.error(`Failed to fetch ${repo}`)
}
}
setupGithubCards()
document.addEventListener('astro:page-load', setupGithubCards)
</script>

View file

@ -1,36 +0,0 @@
<button
id="back-button"
class="hidden"
lg="block absolute c-secondary/25 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/60"
aria-label="Back to home"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
aria-hidden="true"
fill="currentColor"
>
<path d="M17.9.6 4 12l13.8 11.4.7-.9L7.2 12 18.5 1.5l-.7-.9Z"></path>
</svg>
</button>
<!-- Go Back Script >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
<script>
function setupBackButton() {
document.getElementById('back-button')?.addEventListener('click', () => {
if (window.history.length > 1) {
window.history.back()
}
else {
// Click site title link to trigger view transition when no history
const titleLink = document.getElementById('site-title-link') as HTMLAnchorElement
if (titleLink) {
titleLink.click()
}
}
})
}
setupBackButton()
document.addEventListener('astro:after-swap', setupBackButton)
</script>

View file

@ -0,0 +1,111 @@
<script>
import { gsap } from 'gsap'
function setupPostPageAnimation() {
// Animated Elements
const postContent = document.getElementById('gsap-post-page-content')
const postContentChildren = postContent ? Array.from(postContent.children) : []
const tocContainer = document.getElementById('toc-container')
const tocIcon = document.getElementById('toc-icon')
const tocList = document.getElementById('toc-list')
const tocListChildren = tocList ? Array.from(tocList.children) : []
const backButton = document.getElementById('back-button')
const postDate = document.getElementById('gsap-post-page-date')
// Screen Size Check
const isLargeScreen = window.matchMedia('(min-width: 1024px)').matches
const isSmallScreen = window.matchMedia('(max-width: 1535px)').matches
if (isLargeScreen) {
// First 14 elements of post content
gsap.to(postContentChildren.slice(0, 14), {
opacity: 1,
y: 0,
duration: 0.5,
delay: 0.2,
ease: 'power2.out',
stagger: 0.05,
})
// Rest elements of post content as the 15th element
if (postContentChildren.length > 14) {
gsap.to(postContentChildren.slice(14), {
opacity: 1,
y: 0,
duration: 0.5,
delay: 0.2 + 0.05 * 14,
ease: 'power2.out',
})
}
// Post Date
if (postDate) {
gsap.to(postDate, {
opacity: 1,
y: 0,
duration: 0.5,
delay: 0.15,
ease: 'power2.out',
})
}
// TOC Icon
if (tocIcon) {
gsap.to(tocIcon, {
opacity: 1,
y: 0,
duration: 0.5,
delay: 0.25,
ease: 'power2.out',
})
}
// Toc List
if (tocListChildren.length > 0) {
gsap.to(tocListChildren, {
opacity: 1,
y: 0,
duration: 0.5,
delay: 0.25,
ease: 'power2.out',
stagger: 0.025,
})
}
// Back Button
if (backButton) {
gsap.to(backButton, {
opacity: 1,
x: 0,
duration: 0.5,
delay: 0.2,
ease: 'power2.out',
})
}
}
else {
// First 7 elements of post content
gsap.to(postContentChildren.slice(0, 7), {
opacity: 1,
y: 0,
duration: 0.5,
delay: 0.2,
ease: 'power2.out',
stagger: 0.05,
})
}
// TOC Container
if (isSmallScreen && tocContainer) {
gsap.to(tocContainer, {
opacity: 1,
y: 0,
duration: 0.5,
delay: 0.15,
ease: 'power2.out',
})
}
}
setupPostPageAnimation()
document.addEventListener('astro:after-swap', setupPostPageAnimation)
</script>

View file

@ -1,75 +1,67 @@
<script>
import PhotoSwipeLightbox from 'photoswipe/lightbox'
import 'photoswipe/style.css'
import PhotoSwipeLightbox from 'photoswipe/lightbox'
let lightbox: PhotoSwipeLightbox | null = null
const pswp = import('photoswipe')
let lightbox: PhotoSwipeLightbox
const pswp = import('photoswipe')
function cleanup() {
if (lightbox) {
lightbox.destroy()
lightbox = null
function setupPhotoSwipe() {
const bodyElement = document.body
if (bodyElement.hasAttribute('data-photoswipe-initialized'))
return
const article = document.querySelector('article.heti')
const images = article ? article.getElementsByTagName('img') : []
if (images.length === 0)
return
lightbox = new PhotoSwipeLightbox({
gallery: 'article.heti img',
pswpModule: () => pswp,
bgOpacity: 0.9,
padding: {
top: window.innerHeight * 0.1,
bottom: window.innerHeight * 0.1,
left: window.innerWidth * 0.073,
right: window.innerWidth * 0.073,
},
zoom: false,
close: false,
wheelToZoom: true,
imageClickAction: 'close',
tapAction: 'close',
})
// Set image dimensions
lightbox.addFilter('domItemData', (itemData, element) => {
if (element instanceof HTMLImageElement) {
// Set image source
itemData.src = element.src
// Set dimensions with fallback to window size
itemData.w = Number(element.naturalWidth || window.innerWidth)
itemData.h = Number(element.naturalHeight || window.innerHeight)
// Set thumbnail source
itemData.msrc = element.src
}
document.removeEventListener('astro:page-load', createPhotoSwipe)
document.removeEventListener('astro:before-swap', cleanup)
return itemData
})
lightbox.init()
bodyElement.setAttribute('data-photoswipe-initialized', 'true')
}
function lazySetupPhotoSwipe() {
if (typeof window.requestIdleCallback === 'function') {
window.requestIdleCallback(() => setupPhotoSwipe(), { timeout: 1000 })
}
function createPhotoSwipe() {
// Clean up existing instance if any
cleanup()
lightbox = new PhotoSwipeLightbox({
gallery: 'article img',
pswpModule: () => pswp,
closeSVG: '<svg xmlns="http://www.w3.org/2000/svg" height="2.4rem" viewBox="0 -960 960 960" width="3.8rem" fill="#A0A09F"><path d="M480-424 284-228q-11 11-28 11t-28-11q-11-11-11-28t11-28l196-196-196-196q-11-11-11-28t11-28q11-11 28-11t28 11l196 196 196-196q11-11 28-11t28 11q11 11 11 28t-11 28L536-480l196 196q11 11 11 28t-11 28q-11 11-28 11t-28-11L480-424Z"/></svg>',
zoomSVG: '<svg xmlns="http://www.w3.org/2000/svg" height="2.4rem" viewBox="0 -960 960 960" width="3.8rem" fill="#A0A09F"><path d="M340-540h-40q-17 0-28.5-11.5T260-580q0-17 11.5-28.5T300-620h40v-40q0-17 11.5-28.5T380-700q17 0 28.5 11.5T420-660v40h40q17 0 28.5 11.5T500-580q0 17-11.5 28.5T460-540h-40v40q0 17-11.5 28.5T380-460q-17 0-28.5-11.5T340-500v-40Zm40 220q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l224 224q11 11 11 28t-11 28q-11 11-28 11t-28-11L532-372q-30 24-69 38t-83 14Zm0-80q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z"/></svg>',
padding: { top: window.innerHeight * 0.1, bottom: window.innerHeight * 0.1, left: window.innerWidth * 0.06, right: window.innerWidth * 0.06 },
wheelToZoom: true,
arrowPrev: false,
arrowNext: false,
imageClickAction: 'close',
tapAction: 'close',
doubleTapAction: 'zoom',
else {
requestAnimationFrame(() => {
setupPhotoSwipe()
})
// Automatically add image dimensions
lightbox.addFilter('domItemData', (itemData: any, element: Element) => {
if (element instanceof HTMLImageElement) {
itemData.src = element.src
itemData.w = Number(element.naturalWidth || window.innerWidth)
itemData.h = Number(element.naturalHeight || window.innerHeight)
itemData.msrc = element.src
}
return itemData
})
lightbox.init()
}
}
document.addEventListener('astro:page-load', createPhotoSwipe)
document.addEventListener('astro:before-swap', cleanup)
lazySetupPhotoSwipe()
document.addEventListener('astro:page-load', lazySetupPhotoSwipe)
</script>
<style is:global>
.pswp__button {
--at-apply: 'flex items-center justify-center transition';
}
.pswp__button--zoom,
.pswp__button--close {
--at-apply: 'mt-2 lg:mt-4 active:scale-90';
}
.pswp__button--zoom svg:hover,
.pswp__button--close svg:hover {
fill: #BEBEBE;
}
.pswp__button--close {
--at-apply: 'mr-4 lg:mr-8';
}
.pswp__button--zoom {
--at-apply: 'mr--6 lg:mr-0';
}
</style>

View file

@ -1,111 +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 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')
}
})
// 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: 'leave',
autoHideDelay: 500,
},
overflow: {
x: 'hidden',
},
})
tocElement.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.35rem;
--os-padding-perpendicular: 0;
--os-padding-axis: 0;
--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.1rem;
--os-handle-bg: oklch(var(--un-preset-theme-colors-secondary) / 0.15);
--os-handle-bg-hover: oklch(var(--un-preset-theme-colors-secondary) / 0.25);
--os-handle-bg-active: oklch(var(--un-preset-theme-colors-secondary) / 0.25);
--os-handle-min-size: 12%;
}
@media (min-width: 1536px) {
#toc-content .os-scrollbar {
--at-apply: 'hidden';
}
}
</style>

View file

@ -1,5 +1,6 @@
---
import type { MarkdownHeading } from 'astro'
import TocIcon from '@/assets/icons/toc-icon.svg'
import { ui } from '@/i18n/ui'
import { getPageInfo } from '@/utils/page'
@ -13,51 +14,56 @@ const currentUI = ui[currentLang as keyof typeof ui]
const { headings = [] } = Astro.props
const filteredHeadings = headings.filter(heading =>
heading.depth >= 2
&& heading.depth <= 4
&& heading.text !== 'Footnotes',
&& heading.depth <= 4,
)
---
{filteredHeadings.length > 0 && (
// TOC Container
<div
class="mb-6 bg-secondary/5 2xl:(fixed left-0 top-43.5 max-w-[min(calc(50vw-38rem),13rem)] border-none bg-transparent)"
border="~ secondary/5 rounded solid"
id="toc-container"
class="mb-6 uno-round-border bg-secondary/5 2xl:(fixed left-0 top-44.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 h-max w-max flex c-secondary/25 transition-colors ease-out hover:c-secondary/60)"
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>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
{/* Icon on Desktop */}
<TocIcon
id="toc-icon"
aria-hidden="true"
class="ml-1 hidden aspect-square w-4.2 2xl:(mt-4 block origin-center active:scale-90!)"
fill="currentColor"
class="ml-4 hidden aspect-square w-4.2 2xl:(mt-4 block origin-center active:scale-90)"
>
<path d="M22.2 2.3H1.8v1.6h19.8zM1.8 21.7h19.8l.6-1.6H1.8zM15.5 11.2H1.8v1.6h13.1z" />
</svg>
/>
</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={{
@ -87,55 +93,57 @@ const filteredHeadings = headings.filter(heading =>
<!-- Override heti default styles >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> -->
<style>
.toc-title {
--at-apply: 'font-semibold ml-4 select-none 2xl:hidden';
--at-apply: 'ml-4 font-semibold 2xl:hidden';
}
.toc-list {
--at-apply: 'list-none pl-0 space-y-2 mt-1 mb-4 2xl:space-y-1.2';
--at-apply: 'mb-2.5 mt-1 list-none pl-0 space-y-1.1 2xl:(mb-1 space-y-1)';
}
.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-balance text-sm font-normal no-underline 2xl:(text-3.2 c-secondary/60 transition-colors transition-font-weight ease-out hover:c-secondary hover: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 lg:max-h-82 2xl:(max-h-[calc(100vh-21.5rem)]) px-4';
--at-apply: 'max-h-59.3 overflow-hidden pl-4 pr-6 2xl:(max-h-[calc(100vh-26.75rem)] pl-1)';
}
/* When toggle is checked, expand the wrapper to show content */
.accordion-toggle:checked ~ .accordion-wrapper {
grid-template-rows: 1fr;
}
.accordion-toggle:checked ~ .accordion-wrapper .accordion-content {
--at-apply: 'overflow-y-auto';
}
#toc-content {
scrollbar-width: thin;
scrollbar-color: oklch(var(--un-preset-theme-colors-secondary) / 0.15) transparent;
}
@media (min-width: 1536px) {
.accordion-wrapper {
grid-template-rows: 1fr;
}
.accordion-toggle:checked ~ .accordion-wrapper {
grid-template-rows: 0fr;
}
.accordion-content {
--at-apply: 'overflow-y-auto';
}
.accordion-toggle:checked ~ .accordion-wrapper .accordion-content {
--at-apply: 'overflow-hidden';
}
.toc-link-active {
--at-apply: 'c-secondary font-medium';
}
#toc-content {
--at-apply: 'scrollbar-hidden';
}
#toc-content::-webkit-scrollbar {
display: none;
}
}
</style>
@ -146,7 +154,7 @@ function setupTOCHighlight() {
if (!tocContent)
return
const tocLinks = tocContent.querySelectorAll('a')
const tocLinks = tocContent.getElementsByTagName('a')
if (tocLinks.length === 0)
return
@ -155,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)

View file

@ -17,7 +17,7 @@ export const themeConfig: ThemeConfig = {
url: 'https://retypeset.radishzz.cc',
// favicon url
// recommended formats: svg, png or ico
favicon: '/icon/favicon.svg', // or https://example.com/favicon.svg
favicon: '/icons/favicon.svg', // or https://example.com/favicon.svg
},
// SITE INFORMATION >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> END
@ -38,11 +38,8 @@ export const themeConfig: ThemeConfig = {
},
dark: {
// primary color
// used for title, hover, etc
// oklch color picker: https://oklch.com/
primary: 'oklch(92% 0.005 298)',
// secondary color
// used for post text
secondary: 'oklch(77% 0.005 298)',
// background color
background: 'oklch(22% 0.005 298)',
@ -53,18 +50,20 @@ export const themeConfig: ThemeConfig = {
// GLOBAL SETTINGS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> START
global: {
// default language
locale: 'zh', // zh, zh-tw, ja, en, es, ru
locale: 'zh', // de, en, es, fr, ja, ko, pl, pt, ru, zh, zh-tw
// more languages
// not fill in the locale code above again
moreLocales: ['zh-tw', 'ja', 'en', 'es', 'ru'], // ['zh', 'zh-tw', 'ja', 'en', 'es', 'ru']
// not fill in the locale code above again, can be an empty array []
moreLocales: ['en', 'es', 'ja', 'ru', 'zh-tw'], // ['de', 'en', 'es', 'fr', 'ja', 'ko', 'pl', 'pt', 'ru', 'zh', 'zh-tw']
// font styles for post text
fontStyle: 'sans', // sans, serif
// date format for posts
dateFormat: 'YYYY-MM-DD', // YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// gap between title and subtitle
titleGap: 2, // 1, 2, 3
// enable table of contents for all posts by default
toc: true, // true, false
// enable KaTeX for mathematical formulas rendering
katex: true, // true, false
// reduce animations and transitions to improve performance
reduceMotion: false, // true, false
},
// GLOBAL SETTINGS >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> END
@ -87,7 +86,6 @@ export const themeConfig: ThemeConfig = {
// gif search
search: false, // true, false
// image uploader
// bug: unable to hide image uploader icon
imageUploader: false, // true, false
}
},
@ -139,23 +137,23 @@ export const themeConfig: ThemeConfig = {
links: [
{
name: 'RSS',
url: '/rss.xml', // rss.xml, atom.xml
url: '/atom.xml', // or /rss.xml
},
{
name: 'GitHub',
url: 'https://github.com/radishzzz/astro-theme-retypeset',
},
{
name: 'Twitter',
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
@ -164,9 +162,8 @@ 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
// optimize remote images in Markdown files to avoid cumulative layout shift
imageHostURL: 'https://image.radishzz.cc',
// custom google analytics js
// for users who route analytics javascript to a customized domain

View file

@ -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' }),
@ -10,12 +10,15 @@ const posts = defineCollection({
published: z.date(),
// optional
description: z.string().optional().default(''),
updated: z.date().optional(),
updated: z.preprocess(
val => val === '' ? undefined : val,
z.date().optional(),
),
tags: z.array(z.string()).optional().default([]),
// 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),

View file

@ -8,13 +8,13 @@ lang: zh
abbrlink: birth-of-retypeset
---
[Retypeset](https://github.com/radishzzz/astro-theme-retypeset) 是一款基于 Astro 框架的静态博客主题,中文名为重新编排。作为一名编程小白,我花三个月时间开发了这款主题,感受颇多。这篇文章,就来分享一下 Retypeset 诞生的故事。
Retypeset 是一款基于 Astro 框架的静态博客主题,中文名为重新编排。作为一名编程小白,我花三个月时间开发了这款主题,感受颇多。这篇文章,就来分享一下 Retypeset 诞生的故事。
## 初遇
去年入坑博客以后,就很喜欢刷别人的博客。一来是可以看看别人的博客主题,二来是能刷到别人分享的故事。
![活版印字主题](https://image.radishzz.cc/birth-of-retypeset/typograph.webp)
![_活版印字](https://image.radishzz.cc/birth-of-retypeset/typograph.webp)
几个月前,我偶然在 V2 刷到 [活版印字](https://astro-theme-typography.vercel.app/) 这个主题,简约的风格直接戳中我的审美。再加上之前的 Hexo 博客性能太差,我一直想换来着,于是就决定迁移博客到这个主题。
@ -27,14 +27,8 @@ abbrlink: birth-of-retypeset
- 桌面端的部分区域无法滚动
![匀速淡入淡出,略显生硬](https://image.radishzz.cc/birth-of-retypeset/unnatural-animation-rate.gif)
<figure>
<figcaption>匀速淡入淡出,略显生硬</figcaption>
</figure>
<figure>
<img src="https://image.radishzz.cc/birth-of-retypeset/different-margins.webp" alt="移动端左边距为四格,右边距为六格" />
<figcaption>移动端的左边距为四格,右边距为六格</figcaption>
</figure>
![移动端的左边距为四格,右边距为六格](https://image.radishzz.cc/birth-of-retypeset/different-margins.webp)
不过这些倒是小事。对我来说,最大的问题是主题不支持 i18n 功能。我指的 i18n 不是简单地更换 UI 语言,而是支持多语言路径。
@ -44,11 +38,11 @@ i18n 对我来说是必需的。因为我之前发过一篇英文的 [三星优
于是我开始给主题添加 i18n 功能。既然要加,不能只支持中英两种语言,肯定得支持多种语言。根据 Astro 官方指南,我需要给每种语言都新建一个文件夹,这也太麻烦了。
![Astro 官方的 i18n 指南](https://image.radishzz.cc/birth-of-retypeset/astro-i18n-guide.webp)
![_Astro 官方的 i18n 指南](https://image.radishzz.cc/birth-of-retypeset/astro-i18n-guide.webp)
接着我找到官方推荐的 i18n 插件,都试了一遍,效果都不理想,而且很麻烦。后来刷到一个推特帖子,我发现这个方案不错,非常地巧妙,而且不需要安装额外的插件。
![推特 i18n 截图](https://image.radishzz.cc/birth-of-retypeset/twitter-i18n.webp)
![_推特 i18n 截图](https://image.radishzz.cc/birth-of-retypeset/twitter-i18n.webp)
于是我按照这个思路,花了一周时间终于是弄出一套方案。本地测试成功,非常开心。虽然我看不懂 Cursor 是怎么实现的,但能跑起来就行了。
@ -56,9 +50,9 @@ i18n 对我来说是必需的。因为我之前发过一篇英文的 [三星优
无奈之下,我想到了向作者 Moeyua 发邮件求助。
## 转折
![_求助邮件](https://image.radishzz.cc/birth-of-retypeset/mail-to-moeyua.webp)
![邮件截图](https://image.radishzz.cc/birth-of-retypeset/mail-to-moeyua.webp)
## 转折
没想到作者很快回复了我,并帮忙提交 PR 修复了报错问题。但是我发现 i18n 的实现方式被改成了 301 重定向,这显然不是我想要的效果。也不好意思再去麻烦人家作者,试着自己改改吧。
@ -68,7 +62,7 @@ i18n 对我来说是必需的。因为我之前发过一篇英文的 [三星优
三个月过去了,也就有了现在你所看到的样子。
![主题图片](https://image.radishzz.cc/birth-of-retypeset/retypeset-en-desktop.webp)
![_Retypeset](https://image.radishzz.cc/birth-of-retypeset/retypeset-en-desktop.webp)
## 细节
@ -90,27 +84,15 @@ i18n 对我来说是必需的。因为我之前发过一篇英文的 [三星优
二是因为视觉风格。你所看到的字体、颜色、排版、图标、动画等,都是我精心推敲之后的结果。由于篇幅限制,不适合在此展开介绍。不过我相信,你应该能感受到主题背后,那一股优雅的气质。下面分享一些设计过程中的草图:
<figure>
<img src="https://image.radishzz.cc/birth-of-retypeset/draft-01.webp" alt="草图" />
<figcaption>初稿</figcaption>
</figure>
![初稿](https://image.radishzz.cc/birth-of-retypeset/draft-01.webp)
<figure>
<img src="https://image.radishzz.cc/birth-of-retypeset/draft-04.webp" alt="草图" />
<figcaption>尝试在标题上添加一些线条装饰</figcaption>
</figure>
![标题的排列组合](https://image.radishzz.cc/birth-of-retypeset/draft-04.webp)
![草图](https://image.radishzz.cc/birth-of-retypeset/draft-02.webp)
![初始布局](https://image.radishzz.cc/birth-of-retypeset/draft-02.webp)
<figure>
<img src="https://image.radishzz.cc/birth-of-retypeset/draft-03.webp" alt="草图" />
<figcaption>尝试不同配色,包括渐变</figcaption>
</figure>
![尝试不同配色](https://image.radishzz.cc/birth-of-retypeset/draft-03.webp)
<figure>
<img src="https://image.radishzz.cc/birth-of-retypeset/draft-05.webp" alt="草图" />
<figcaption>主题切换按键,其实是旋转 90 度的字母 O</figcaption>
</figure>
![绘制图标](https://image.radishzz.cc/birth-of-retypeset/draft-05.webp)
### Webkit
@ -120,9 +102,9 @@ iPhone 上总是会出现一些奇怪的 BUG例如切换页面时背景会闪
以下图片均为慢动作拍摄。
![草图](https://image.radishzz.cc/birth-of-retypeset/bug-01.gif)
![字体被裁切](https://image.radishzz.cc/birth-of-retypeset/bug-01.gif)
![草图](https://image.radishzz.cc/birth-of-retypeset/bug-02.gif)
![背景闪烁](https://image.radishzz.cc/birth-of-retypeset/bug-02.gif)
为了解决这些奇怪的问题,我也是花了不少时间,好在最后都完美解决了。如果你在仓库中搜 ios你可以看到不少注释那些就是我的解决办法。
@ -154,9 +136,4 @@ iPhone 上总是会出现一些奇怪的 BUG例如切换页面时背景会闪
- [Moeyua](https://github.com/moeyua) 原主题作者,提供 PR 与故事的开始
- [Xat](https://github.com/withxat) 热心老哥,在发帖求助两个月后主动联系我,提供 PR 与意见参考
<figure>
<img src="https://image.radishzz.cc/birth-of-retypeset/xat-help.webp" alt="草图" />
<figcaption>世上还是好人多啊。<del>也不多,就一个</del></figcaption>
</figure>
完。
![世上还是好人多啊](https://image.radishzz.cc/birth-of-retypeset/xat-help.webp)

View file

@ -1,6 +1,7 @@
---
title: Universal Article
published: 2025-03-24
draft: true
# lang: ''
description: This is a universal multilingual article with unspecified 'lang', displayed by default across all language-specific paths. Este es un artículo universal multilingüe sin definir 'lang', visible por defecto en todas las rutas de idiomas.
---
@ -13,14 +14,35 @@ published: 2025-03-24
---
```
<!-- German (de) -->
Dies ist ein universeller mehrsprachiger Artikel ohne spezifizierte 'lang'-Angabe, der standardmäßig in allen sprachspezifischen Pfaden angezeigt wird.
<!-- English (en) -->
This is a universal multilingual article with unspecified 'lang', displayed by default across all language-specific paths.
<!-- Spanish (es) -->
Este es un artículo universal multilingüe sin definir 'lang', visible por defecto en todas las rutas de idiomas.
<!-- French (fr) -->
Ceci est un article universel multilingue sans spécification de 'lang', affiché par défaut dans tous les chemins spécifiques aux langues.
<!-- Japanese (ja) -->
これは言語パラメータlang未指定の汎用マルチリンガル記事です。全言語パスでデフォルト表示されます。
<!-- Korean (ko) -->
이것은 'lang'을 지정하지 않은 다국어 범용 기사로, 기본적으로 모든 언어별 경로에 표시됩니다.
<!-- Polish (pl) -->
To jest uniwersalny wielojęzyczny artykuł bez określonego parametru 'lang', wyświetlany domyślnie we wszystkich ścieżkach specyficznych dla języka.
<!-- Portuguese (pt) -->
Este é um artigo universal multilínguas sem definir 'lang', visível por padrão através de todas as rotas de linguagem.
<!-- Russian (ru) -->
Это универсальная многоязычная статья без указания 'lang', отображаемая по умолчанию во всех языковых разделах.
<!-- Chinese Simplified (zh) -->
这是一篇未指定 lang 的多语言通用文章,默认显示在所有语言路径下。
<!-- Chinese Traditional (zh-tw) -->
這是一篇未指定 lang 的多語言通用文章,預設顯示於所有語言路徑下。
これは言語パラメータlang未指定の汎用マルチリンガル記事です。全言語パスでデフォルト表示されます。

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,005 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,016 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View file

@ -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.

View file

@ -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.

View file

@ -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の加法群です。

View file

@ -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.

View file

@ -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 為模的實數加法群。

View file

@ -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 为模的实数加法群。

View file

@ -1,7 +1,9 @@
---
title: Tolerance and Freedom
published: 1959-03-16
tags: ["Hu Shih","Modern Literature"]
tags:
- Hu Shih
- Modern Literature
lang: en
abbrlink: tolerance-freedom
---

View file

@ -1,12 +1,14 @@
---
title: Tolerancia y Libertad
published: 1959-03-16
tags: ["Hu Shih","Literatura Moderna"]
tags:
- Hu Shih
- Literatura Moderna
lang: es
abbrlink: tolerance-freedom
---
Hace diecisiete o dieciocho años conocí por última vez al señor George Lincoln Burr, un gran historiador de mi alma mater, la Universidad de Cornell. Hablamos del historiador británico Lord Acton, quien planeó escribir una Historia de la Libertad a lo largo de su vida, pero murió antes de poder terminarla. El señor Bull habló mucho ese día y hay una frase que nunca he olvidado. Dijo: "Cuanto mayor me hago, más siento que la tolerancia es más importante que la libertad".
Hace diecisiete o dieciocho años conocí por última vez al señor George Lincoln Burr, un gran historiador de mi alma mater, la Universidad de Cornell. Hablamos del historiador británico Lord Acton, quien planeó escribir una Historia de la Libertad a lo largo de su vida, pero murió antes de poder terminarla. El señor Bull habló mucho ese día y hay una frase que nunca he olvidado. Dijo: «Cuanto mayor me hago, más siento que la tolerancia es más importante que la libertad».
El señor Bull murió hace más de diez años, pero cuanto más pienso en ello, más siento que es un lema indeleble. Yo mismo tengo la misma sensación de que "cuanto mayor me hago, más siento que la tolerancia es más importante que la libertad". A veces incluso siento que la tolerancia es la raíz de toda libertad: sin tolerancia, no hay libertad.
@ -40,7 +42,7 @@ Todas las persecuciones de herejes, toda destrucción de "disidentes", todas las
Consideremos la historia de la Reforma en Europa. Martín Lutero, Juan Calvino y otros se levantaron para reformar la religión porque estaban insatisfechos con la intolerancia y la falta de libertad de la Iglesia Católica Romana. Sin embargo, después de la victoria del protestantismo en Europa central y septentrional, los líderes protestantes se volvieron gradualmente intolerables y ya no permitieron que otros criticaran sus nuevas doctrinas. Calvino tenía el poder religioso en Ginebra, pero en realidad condenó a Servet, un erudito que se atrevió a pensar independientemente y criticar el dogma de Calvino, por "herejía", lo encadenó a una estaca, apiló leña sobre él y lo quemó vivo lentamente. Esto ocurrió el 23 de octubre de 1553.
La trágica historia de este mártir Servet es muy digna de ser recordada y reflexionada. El objetivo original del movimiento de Reforma era luchar por la "libertad cristiana" y la "libertad de conciencia". ¿Por qué Calvino y sus seguidores quemarían a fuego lento a un protestante de mentalidad independiente? ¿Por qué el discípulo de Calvino (y más tarde su sucesor como dictador religioso de Ginebra) de Bèze declaró que "la libertad de conciencia es el dogma del diablo"?
La trágica historia de este mártir Servet es muy digna de ser recordada y reflexionada. El objetivo original del movimiento de Reforma era luchar por la "libertad cristiana" y la "libertad de conciencia". ¿Por qué Calvino y sus seguidores quemarían a fuego lento a un protestante de mentalidad independiente? ¿Por qué el discípulo de Calvino (y más tarde su sucesor como dictador religioso de Ginebra) de Bèze declaró que «la libertad de conciencia es el dogma del diablo»?
La razón básica es que creo firmemente que nunca puedo equivocarme. Un reformador religioso devoto como Calvino creía firmemente que su conciencia representaba verdaderamente los mandamientos de Dios, y que su boca y su pluma representaban verdaderamente la voluntad de Dios. Entonces, ¿podrían sus opiniones estar equivocadas? ¿Es posible que esté equivocado? Después de que Servet fue quemado en la hoguera, Calvino fue criticado por mucha gente. En 1554, Calvino publicó un texto de defensa, en el que decía sin dudar: «La autoridad para castigar severamente a los herejes es incuestionable, porque es Dios mismo quien habla. ... Esta obra es una lucha por la gloria de Dios».

View file

@ -1,64 +1,66 @@
---
title: 寛容と自由
published: 1959-03-16
tags: ["胡適","きんだいぶんがく"]
tags:
- 胡適
- きんだいぶんがく
lang: ja
abbrlink: tolerance-freedom
---
今から17、18年前、私は母校コニヤース大学の歴史学修士ジョージ・リンカーン・バー氏と最後に会った。 私たちは、生前に執筆を準備していた『自由の歴史』を書かずに亡くなった英国の歴史家アクトン卿について話していた。 その日、バー氏は多くの会話を交わしたが、その中で私が今でも忘れられない一文があった。 年を取れば取るほど、自由よりも寛容の方が大切だと感じるようになる」と。
今から17、18年前、私は母校コニヤース大学の歴史学修士ジョージ・リンカーン・バー氏と最後に会った。私たちは、生前に執筆を準備していた『自由の歴史』を書かずに亡くなった英国の歴史家アクトン卿について話していた。その日、バー氏は多くの会話を交わしたが、その中で私が今でも忘れられない一文があった。年を取れば取るほど、自由よりも寛容の方が大切だと感じるようになる」と。
ブリュワー氏が亡くなって10年以上が経つが、彼のこの言葉は考えれば考えるほど、忘れられない格言だと感じる。 私自身、「年を取れば取るほど、自由よりも寛容さの方が大切だと感じるようになる」という思いもある。 寛容さこそがすべての自由の本質であり、それなくして自由はないとさえ思うことがある。
ブリュワー氏が亡くなって10年以上が経つが、彼のこの言葉は考えれば考えるほど、忘れられない格言だと感じる。私自身、「年を取れば取るほど、自由よりも寛容さの方が大切だと感じるようになる」という思いもある。寛容さこそがすべての自由の本質であり、それなくして自由はないとさえ思うことがある。
私が17歳のとき1908年、私は『競争倫敦新聞』にいくつかの記事を掲載した。その中には、小説『西遊記』や『風神榜』をこき下ろしたものもあり、私はこう言った
「幽霊や神々の捏造、時日占いで群衆を疑い、殺す"。 私はただ権力の数千年の行支配を責めて、世界と人民の自己期待への道を助けるために、無知で注意を払わないで、世界と虚偽の人民の教義を混同して実践することができて、そして私の神の状態を闇の世界に引き上げた!
「幽霊や神々の捏造、時日占いで群衆を疑い、殺す"。私はただ権力の数千年の行支配を責めて、世界と人民の自己期待への道を助けるために、無知で注意を払わないで、世界と虚偽の人民の教義を混同して実践することができて、そして私の神の状態を闇の世界に引き上げた!
これは「道の守護」に対する子供の非常に不寛容な態度だった。 当時、私はすでに無霊・無神論者であったので、迷信を滅ぼすというあのような荒唐無稽な主張をし、『王制』の古典の一つ(『礼記』の一篇)である「幽霊や神を根拠に占いで民衆を疑えば、殺される」という言葉を実行に移したかったのである!
これは「道の守護」に対する子供の非常に不寛容な態度だった。当時、私はすでに無霊・無神論者であったので、迷信を滅ぼすというあのような荒唐無稽な主張をし、『王制』の古典の一つ(『礼記』の一篇)である「幽霊や神を根拠に占いで民衆を疑えば、殺される」という言葉を実行に移したかったのである!
このように言った小さな子供が、15年後1923年、西遊記について2万字に及ぶ考察をするほどの熱意を持つようになるとは、その時は夢にも思わなかった! その小さな子供が、20年後、30年後も『神々のタブレット』の作者であることを証明できる資料を探し続けているとは、その時は夢にも思わなかった また、『王制』の一節が歴史的に重要であるなどとは、当時はまったく考えてもいなかった。 その『王制』の一節の全文はこうだ:
このように言った小さな子供が、15年後1923年、西遊記について 2 万字に及ぶ考察をするほどの熱意を持つようになるとは、その時は夢にも思わなかったその小さな子供が、20年後、30年後も『神々のタブレット』の作者であることを証明できる資料を探し続けているとは、その時は夢にも思わなかったまた、『王制』の一節が歴史的に重要であるなどとは、当時はまったく考えてもいなかった。その『王制』の一節の全文はこうだ
言葉を解析して法を破り、人の名を変え、左の道をたどって政を乱す者は殺せ。 わいせつな音を立てたり、奇妙な衣装を着たりして、人々に不審を抱かせる者は殺せ。 線は偽りで堅く、言葉は偽りで弁証法的であり、学問は広くはないが、滑らかな非ゼファーは群衆を疑うことであり、殺すことである。 幽霊、神、時、日、占いのふりをして民衆を疑い、殺すことである。 この4人の殺し屋の言うことは聞いてはいけない。
言葉を解析して法を破り、人の名を変え、左の道をたどって政を乱す者は殺せ。わいせつな音を立てたり、奇妙な衣装を着たりして、人々に不審を抱かせる者は殺せ。線は偽りで堅く、言葉は偽りで弁証法的であり、学問は広くはないが、滑らかな非ゼファーは群衆を疑うことであり、殺すことである。幽霊、神、時、日、占いのふりをして民衆を疑い、殺すことである。この4人の殺し屋の言うことは聞いてはいけない。
50年前、私はこの一節の「罰」が、中国の権威主義体制下で新しい思想、新しい学問、新しい信仰、新しい芸術を禁止する古典的な根拠であることをまったく理解していなかった。 当時、私は「迷信を打破する」という熱意を抱いていたので、「四刑」の4番目の 「幽霊や神、時日占いを偽って大衆を疑う者は殺せ 」を支持した。 当時は、四罪の「幽霊や神......大衆を疑う」と一罪の「政府を混乱させる左翼」が、信教の自由を破壊するために使われるとは思っていなかった。 その時、私はまた、鄭玄のメモが「奇妙な技法と外国の武器」として、公図蛮の例を用いていることに気づかなかった。さらに言えば、孔英大の『正義』が「孔子は7日間魯の参謀だったが、邵正茂を処刑した」という例を挙げて、「......」と説明していることにも気づかなかった。 第二の刑罰は、その人の行動を禁止するために用いることができるが、その人の言論を禁止するために用いることはできない。 したがって、第二の罰は芸術創作の自由を禁止するために使用することができ、また「奇妙な技術や奇妙な武器」を発明した多くの科学者を「殺す」ために使用することができる。 したがって、第三の刑罰は、思想の自由、言論の自由、出版の自由を破壊するために使われる可能性がある。
50 年前、私はこの一節の「罰」が、中国の権威主義体制下で新しい思想、新しい学問、新しい信仰、新しい芸術を禁止する古典的な根拠であることをまったく理解していなかった。当時、私は「迷信を打破する」という熱意を抱いていたので、「四刑」の4番目の 「幽霊や神、時日占いを偽って大衆を疑う者は殺せ 」を支持した。当時は、四罪の「幽霊や神......大衆を疑う」と一罪の「政府を混乱させる左翼」が、信教の自由を破壊するために使われるとは思っていなかった。その時、私はまた、鄭玄のメモが「奇妙な技法と外国の武器」として、公図蛮の例を用いていることに気づかなかった。さらに言えば、孔英大の『正義』が「孔子は7日間魯の参謀だったが、邵正茂を処刑した」という例を挙げて、「......」と説明していることにも気づかなかった。第二の刑罰は、その人の行動を禁止するために用いることができるが、その人の言論を禁止するために用いることはできない。したがって、第二の罰は芸術創作の自由を禁止するために使用することができ、また「奇妙な技術や奇妙な武器」を発明した多くの科学者を「殺す」ために使用することができる。したがって、第三の刑罰は、思想の自由、言論の自由、出版の自由を破壊するために使われる可能性がある。
50年前、私は『西遊記』と『神々の創世』の著者を「殺す」ために、王制の第4の罰を発動した。 その時はもちろん、10年後、私が北京大学で教鞭をとっていた時、同じ「道の擁護者」でありながら、私と私の友人を「殺す」ために「王制」の第三の刑罰を発動しようとする正義の人々が現れるとは夢にも思わなかった。 当時、私は人を「殺したい」と思い、後に人は私を「殺したい」と思ったが、動機は同じで、ちょっとした正義の怒りのために寛容さを失ったのである。
50 年前、私は『西遊記』と『神々の創世』の著者を「殺す」ために、王制の第 4 の罰を発動した。その時はもちろん、 10年後、私が北京大学で教鞭をとっていた時、同じ「道の擁護者」でありながら、私と私の友人を「殺す」ために「王制」の第三の刑罰を発動しようとする正義の人々が現れるとは夢にも思わなかった。当時、私は人を「殺したい」と思い、後に人は私を「殺したい」と思ったが、動機は同じで、ちょっとした正義の怒りのために寛容さを失ったのである。
私が50年前、幽霊や神や時間や日に頼って占いをする人々を殺すことを提唱した話をしたのは、年を取れば取るほど、「自由」よりも「寛容」の方が大切だと感じるようになることを説明するためである。 私は今日も無神論者である。
私が 50 年前、幽霊や神や時間や日に頼って占いをする人々を殺すことを提唱した話をしたのは、年を取れば取るほど、「自由」よりも「寛容」の方が大切だと感じるようになることを説明するためである。私は今日も無神論者である。
私は現在も無神論者であり、意志を持った神を信じていないし、魂の不滅を信じているわけでもない。 しかし、私の無神論と共産党の無神論には根本的な違いがある。 私は神を信じるすべての宗教を容認することができるし、宗教を心から信じるすべての人々を容認することができる。 無神論を標榜する共産党自身が、神への信仰をすべて破壊し、神のいる宗教への信仰をすべて禁止しようとしている--50年前の私の幼稚で傲慢な不寛容は、そのようなものだった。
私は現在も無神論者であり、意志を持った神を信じていないし、魂の不滅を信じているわけでもない。しかし、私の無神論と共産党の無神論には根本的な違いがある。私は神を信じるすべての宗教を容認することができるし、宗教を心から信じるすべての人々を容認することができる。無神論を標榜する共産党自身が、神への信仰をすべて破壊し、神のいる宗教への信仰をすべて禁止しようとしている-- 50 年前の私の幼稚で傲慢な不寛容は、そのようなものだった。
私自身は、国民の大多数が神を信じているこの国、この社会、この世界には、私の無神論を容認し、神も魂の不滅も信じていない私を容認し、私が国内外で無神論的な考えを自由に表現することを容認する優しさがあり、そのために私を石で投げつけたり、牢獄に閉じ込めたり、薪の上に束ねて火で焼いたりする人はいないと、いつも感じていた。 実際、私はこの世界で40年以上も寛容と自由を享受してきた。 この国、この社会、この世界が私に示してくれた寛容の尺度は素敵なものであり、感謝に値するものだと感じている。
私自身は、国民の大多数が神を信じているこの国、この社会、この世界には、私の無神論を容認し、神も魂の不滅も信じていない私を容認し、私が国内外で無神論的な考えを自由に表現することを容認する優しさがあり、そのために私を石で投げつけたり、牢獄に閉じ込めたり、薪の上に束ねて火で焼いたりする人はいないと、いつも感じていた。実際、私はこの世界で 40 年以上も寛容と自由を享受してきた。この国、この社会、この世界が私に示してくれた寛容の尺度は素敵なものであり、感謝に値するものだと感じている。
だから私自身は、社会の私に対する寛容さに寛容さで報いるべきだと常に思っている。 したがって、私は神を信じていないが、神を信じるすべての人々を心から理解することができるし、神を信じるすべての宗教を心から許容し、尊重することができる。
だから私自身は、社会の私に対する寛容さに寛容さで報いるべきだと常に思っている。したがって、私は神を信じていないが、神を信じるすべての人々を心から理解することができるし、神を信じるすべての宗教を心から許容し、尊重することができる。
私は社会の寛容さに寛容さで報いたい。年を重ねるごとに、寛容さの大切さを感じるようになったからだ。 もし社会が寛容でなかったら、私は40年以上にわたって大胆な懐疑の自由を享受することも、無神論を公に主張する自由を得ることもできなかっただろう。
私は社会の寛容さに寛容さで報いたい。年を重ねるごとに、寛容さの大切さを感じるようになったからだ。もし社会が寛容でなかったら、私は 40 年以上にわたって大胆な懐疑の自由を享受することも、無神論を公に主張する自由を得ることもできなかっただろう。
宗教の自由の歴史を見ても、知的自由の歴史を見ても、政治的自由の歴史を見ても、寛容という態度が最も稀有なものであることがわかる。 人間は常に、異なるものよりも同じものを好み、自分とは異なる信念、思考、行動を嫌う習性がある。 これが不寛容の根源である。 不寛容とは単に、自分とは異なる新しい考えや新しい信念に対する不寛容である。 宗教団体は常に、自分たちの宗教的信念が正しく、間違っているはずがないと信じているので、自分たちと異なる宗教的信念は間違っているに違いない、異端であるに違いない、カルトであるに違いないと常に信じている。 政治団体は常に、自分たちの政治的意見は正しく、間違ってはならないと信じている。だから、自分たちと異なる政治的意見は間違っているに違いなく、敵に違いないと常に信じている。
宗教の自由の歴史を見ても、知的自由の歴史を見ても、政治的自由の歴史を見ても、寛容という態度が最も稀有なものであることがわかる。人間は常に、異なるものよりも同じものを好み、自分とは異なる信念、思考、行動を嫌う習性がある。これが不寛容の根源である。不寛容とは単に、自分とは異なる新しい考えや新しい信念に対する不寛容である。宗教団体は常に、自分たちの宗教的信念が正しく、間違っているはずがないと信じているので、自分たちと異なる宗教的信念は間違っているに違いない、異端であるに違いない、カルトであるに違いないと常に信じている。政治団体は常に、自分たちの政治的意見は正しく、間違ってはならないと信じている。だから、自分たちと異なる政治的意見は間違っているに違いなく、敵に違いないと常に信じている。
異端者に対する迫害も、「異論者」に対する破壊も、信教の自由の禁止も、思想や言論の弾圧も、すべて「人は間違ってはならない」という信念によるものだ。 自分が間違っているはずがないという信念があるからこそ、人は自分と異なる思想や信念を容認することができない。
異端者に対する迫害も、「異論者」に対する破壊も、信教の自由の禁止も、思想や言論の弾圧も、すべて「人は間違ってはならない」という信念によるものだ。自分が間違っているはずがないという信念があるからこそ、人は自分と異なる思想や信念を容認することができない。
ヨーロッパにおける宗教刷新運動の歴史を見てみよう。 マルティン・ルターとジョン・カルヴァンが宗教に革命を起こそうと立ち上がったのは、もともと古いローマ宗教の不寛容さと自由のなさに不満を持っていたからだ。 しかし、中欧と北欧でプロテスタンティズムが勝利した後、プロテスタンティズムの指導者たちは次第に不寛容に戻り、自分たちの新しい教義を他人が批判することを許さなくなった。 ジュネーブで宗教的権力を握っていたガルヴァンは、ガルヴァンの教義を批判し、独自の思想を持つことを敢えてした学者セルヴェトゥスを、実際に「異端」として有罪にし、杭に鎖でつないで薪を積み上げ、ゆっくりと生きたまま焼き殺した。 1553年10月23日の出来事である。
ヨーロッパにおける宗教刷新運動の歴史を見てみよう。マルティン・ルターとジョン・カルヴァンが宗教に革命を起こそうと立ち上がったのは、もともと古いローマ宗教の不寛容さと自由のなさに不満を持っていたからだ。しかし、中欧と北欧でプロテスタンティズムが勝利した後、プロテスタンティズムの指導者たちは次第に不寛容に戻り、自分たちの新しい教義を他人が批判することを許さなくなった。ジュネーブで宗教的権力を握っていたガルヴァンは、ガルヴァンの教義を批判し、独自の思想を持つことを敢えてした学者セルヴェトゥスを、実際に「異端」として有罪にし、杭に鎖でつないで薪を積み上げ、ゆっくりと生きたまま焼き殺した。1553年10月23日の出来事である。
この殉教者セビトゥスの悲劇的な歴史は、想起と考察に最も値するものである。 宗教刷新運動の本来の目的は、「キリスト教的人間の自由」と「良心の自由」のために戦うことだった。 なぜガルヴァンとその信奉者たちは、独立心の強いプロテスタントを徐火で焼き殺したのか? ガルヴァンの弟子の一人であるド・ベーズ(後にガルヴァンの後継者としてジュネーブの宗教独裁者となる)が、「良心の自由は悪魔の教義である」と宣言したのはなぜか。
この殉教者セビトゥスの悲劇的な歴史は、想起と考察に最も値するものである。宗教刷新運動の本来の目的は、「キリスト教的人間の自由」と「良心の自由」のために戦うことだった。なぜガルヴァンとその信奉者たちは、独立心の強いプロテスタントを徐火で焼き殺したのか?ガルヴァンの弟子の一人であるド・ベーズ(後にガルヴァンの後継者としてジュネーブの宗教独裁者となる)が、「良心の自由は悪魔の教義である」と宣言したのはなぜか。
その基本的な理由は、自分自身は「悪いことはできない」という小さな確信にある。 もしガルヴァンのような敬虔な改革者が、自分の良心が本当に神の命令を表しており、自分の口とペンが本当に神の意志を表していると確信していたとしたら、彼の意見が間違っている可能性はあるのだろうか? 彼が間違っている可能性はあるのだろうか? セルベトゥスの火刑の後、ガルヴァンは多くの人々から批判を受けたが、1554年、彼は自分自身を弁護する文章を発表し、その中で、「悪を語る者を厳しく罰する権威は疑う余地がない。 ......この仕事は神の栄光のために戦っている」
その基本的な理由は、自分自身は「悪いことはできない」という小さな確信にある。もしガルヴァンのような敬虔な改革者が、自分の良心が本当に神の命令を表しており、自分の口とペンが本当に神の意志を表していると確信していたとしたら、彼の意見が間違っている可能性はあるのだろうか彼が間違っている可能性はあるのだろうかセルベトゥスの火刑の後、ガルヴァンは多くの人々から批判を受けたが、1554年、彼は自分自身を弁護する文章を発表し、その中で、「悪を語る者を厳しく罰する権威は疑う余地がない。...... この仕事は神の栄光のために戦っている」
神ご自身が語ることが悪いことだろうか? 神の栄光のために戦うことが悪いことだろうか? この 「私は間違っていない 」という小さな考え方が、あらゆる不寛容の根源なのだ。 自分の信念は絶対であり、自分の意見は 「正義 」であり、反対する者はもちろん 「異端者 」である。 私の意見は神の意志を代弁するものであり、私に反対する者の意見はもちろん「悪魔の教義」である。
神ご自身が語ることが悪いことだろうか?神の栄光のために戦うことが悪いことだろうか?この 「私は間違っていない 」という小さな考え方が、あらゆる不寛容の根源なのだ。自分の信念は絶対であり、自分の意見は 「正義 」であり、反対する者はもちろん 「異端者 」である。私の意見は神の意志を代弁するものであり、私に反対する者の意見はもちろん「悪魔の教義」である。
これは信教の自由の歴史が教えてくれる教訓である。寛容はすべての自由の基礎であり、「異端者」を寛容する恵みがなければ、「異端」の宗教的信念が自由を享受することは認められない。 しかし、不寛容は「私の信念は間違っていない」という精神的習慣に基づくものであるため、「異論」に対する寛容は、寛容の中でも最も希少で、最も培われていないものである。
これは信教の自由の歴史が教えてくれる教訓である。寛容はすべての自由の基礎であり、「異端者」を寛容する恵みがなければ、「異端」の宗教的信念が自由を享受することは認められない。しかし、不寛容は「私の信念は間違っていない」という精神的習慣に基づくものであるため、「異論」に対する寛容は、寛容の中でも最も希少で、最も培われていないものである。
政治的思考や社会問題の議論においても、不寛容は一般的であり、寛容は常に稀であると感じる。 例として、亡くなった旧友の話を挙げよう。 40年以上前、雑誌『新青年』で方言文学を提唱する運動を始めたとき、私はアメリカから全斗秀に手紙を送り、こう言った
政治的思考や社会問題の議論においても、不寛容は一般的であり、寛容は常に稀であると感じる。例として、亡くなった旧友の話を挙げよう。40年以上前、雑誌『新青年』で方言文学を提唱する運動を始めたとき、私はアメリカから全斗秀に手紙を送り、こう言った
この問題の善悪は一朝一夕に決められるものではないし、一人や二人で決められるものでもない。 私は、国内の人々が冷静かつ平和的な方法で、私たちとともにこの問題を研究してくれることを強く望んでいる。 議論が成熟すれば、善悪は明らかになるだろう。 私たちは革命の旗を掲げたが、後退することはできないが、私たちが主張することを必ずそうでなければならないとし、他者にそれを修正させない勇気はない。
この問題の善悪は一朝一夕に決められるものではないし、一人や二人で決められるものでもない。私は、国内の人々が冷静かつ平和的な方法で、私たちとともにこの問題を研究してくれることを強く望んでいる。議論が成熟すれば、善悪は明らかになるだろう。私たちは革命の旗を掲げたが、後退することはできないが、私たちが主張することを必ずそうでなければならないとし、他者にそれを修正させない勇気はない。
杜秀は『新青年』で私にこう答えた:
私は、異論を受け入れることを意味し、自由な議論は、学術発展の原則であり、唯一の本格的な格言として、中国語の文学の改善で、その正誤は非常に明確であり、反対派が部屋の議論を持って許可されません。
当時、私はこれは非常に独断的な態度だと思った。 それから40年以上たった今でも、私は杜秀のこの言葉を忘れることができない。そして、この「自分たちの主張することを絶対的な権利とする」という態度は、非常に不寛容な態度であり、他人の悪感情を最も呼び起こしやすく、最も反発を招きやすい態度だと今でも思っている。
当時、私はこれは非常に独断的な態度だと思った。それから40年以上たった今でも、私は杜秀のこの言葉を忘れることができない。そして、この「自分たちの主張することを絶対的な権利とする」という態度は、非常に不寛容な態度であり、他人の悪感情を最も呼び起こしやすく、最も反発を招きやすい態度だと今でも思っている。
私はかつて、社会が私に対して寛容であることに寛容な態度で報いるべきだと言ったことがある。 もし他人に自分の意見を許容し、理解してもらいたいのであれば、まず自分が他人の意見を許容し、理解する尺度を身につけなければならない。 少なくとも、「自分の主張が絶対的に正しいと思い込む」ようなことは決してしてはならない。 実験主義の訓練を受けてきた私たちは、「絶対的なイエス」を認めないし、ましてや私たちが主張することを「絶対的なイエスとする」ことなどできない。
私はかつて、社会が私に対して寛容であることに寛容な態度で報いるべきだと言ったことがある。もし他人に自分の意見を許容し、理解してもらいたいのであれば、まず自分が他人の意見を許容し、理解する尺度を身につけなければならない。少なくとも、「自分の主張が絶対的に正しいと思い込む」ようなことは決してしてはならない。実験主義の訓練を受けてきた私たちは、「絶対的なイエス」を認めないし、ましてや私たちが主張することを「絶対的なイエスとする」ことなどできない。
4-8, 3-12 朝

View file

@ -1,7 +1,9 @@
---
title: Терпимость и Свобода
published: 1959-03-16
tags: ["Ху Ши","Современная литература"]
tags:
- Ху Ши
- Современная литература
lang: ru
abbrlink: tolerance-freedom
---
@ -62,4 +64,4 @@ abbrlink: tolerance-freedom
48, 3, 12 утра
(Первоначально опубликовано в журнале «Free China» в Тайбэе, том 20, № 6, 16 марта 1959 г.)
(Первоначально опубликовано в журнале «Free China» в Тайбэе, том 20, № 6, 16 марта 1959 г.)

View file

@ -1,7 +1,9 @@
---
title: 容忍與自由
published: 1959-03-16
tags: ["胡適","近代文學"]
tags:
- 胡適
- 近代文學
lang: zh-tw
abbrlink: tolerance-freedom
---

View file

@ -1,7 +1,9 @@
---
title: 容忍与自由
published: 1959-03-16
tags: ["胡适","近代文学"]
tags:
- 胡适
- 近代文学
lang: zh
abbrlink: tolerance-freedom
---

View file

@ -1,12 +1,14 @@
---
title: My Native Heath
published: 1921-01-10
tags: ["Lu Xun","Modern Literature"]
tags:
- Lu Xun
- Modern Literature
lang: en
abbrlink: my-native-heath
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
It was bitter cold as I set forth, after an absence of more than twenty years, on a visit to my native heath over two thousand li away.

View file

@ -1,12 +1,14 @@
---
title: Mi Pueblo Natal
published: 1921-01-10
tags: ["Lu Xun","Literatura Moderna"]
tags:
- Lu Xun
- Literatura Moderna
lang: es
abbrlink: my-native-heath
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
Hacía un frío glacial cuando, tras una ausencia de más de veinte años, partí para visitar mi páramo natal, a más de dos mil li de distancia.
@ -100,7 +102,7 @@ Sí, ahora lo recordaba. De mis recuerdos de infancia, recordaba la imagen de la
"No soy rico. Tengo que vender estas cosas para ... "
¿Qué dices? Te han nombrado Daotai y, sin embargo, dices que no eres rico. Tienes tres concubinas y viajas en un carruaje enorme con ocho porteadores, ¡y me dices que no eres rico! ¡Heng , no puedes engañarme!
¿Qué dices? Te han nombrado Daotai y, sin embargo, dices que no eres rico. Tienes tres concubinas y viajas en un carruaje enorme con ocho porteadores, ¡y me dices que no eres rico! ¡Heng, no puedes engañarme!
Me di cuenta de que no tenía sentido discutir con ella y me quedé callado.
@ -146,7 +148,7 @@ Por la tarde, escogió algunas cosas que podría usar: dos mesas largas, cuatro
Por la noche volvimos a charlar, sin ningún tema en particular. A la mañana siguiente se fue con Shui-sheng.
Nueve días después, dejamos nuestro antiguo hogar. Yun-t'u llegó temprano por la mañana. No trajo a Shui-sheng, sino a una niña de cinco años para vigilar el barco. Estuvimos ocupados todo el día y tuvimos pocas oportunidades de charlar. Había muchos invitados: algunos habían venido a despedirnos, otros a buscar cosas, y otros tanto a despedirnos como a buscar cosas. Cuando finalmente zarpamos, al anochecer, la vieja casa estaba vacía de todo lo que pudiera ser útil.
Nueve días después, dejamos nuestro antiguo hogar. Yun-t'u llegó temprano por la mañana. No trajo a Shui-sheng, sino a una niña de cinco años para vigilar el barco. Estuvimos ocupados todo el día y tuvimos pocas oportunidades de charlar. Había muchos invitados: algunos habían venido a despedirnos, otros a buscar cosas, y otros tantos a despedirnos como a buscar cosas. Cuando finalmente zarpamos, al anochecer, la vieja casa estaba vacía de todo lo que pudiera ser útil.
Nuestro barco avanzaba lentamente, dejando atrás las colinas verdes que se oscurecían a ambas orillas. Hung-erh, que había estado observando el paisaje oscuro conmigo desde una ventana, me dijo de repente: «Tío, ¿cuándo volvemos?».

View file

@ -1,12 +1,14 @@
---
title: 故郷
published: 1921-01-10
tags: ["ろじん","きんだいぶんがく"]
tags:
- ろじん
- きんだいぶんがく
lang: ja
abbrlink: my-native-heath
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
わたしは厳寒を冒して、二千余里を隔て二十余年も別れていた故郷に帰って来た。時はもう冬の最中で故郷に近づくに従って天気は小闇くなり、身を切るような風が船室に吹き込んでびゅうびゅうと鳴る。苫の隙間から外を見ると、蒼黄いろい空の下にしめやかな荒村があちこちに横たわっていささかの活気もない。わたしはうら悲しき心の動きが抑え切れなくなった。
@ -20,9 +22,9 @@ abbrlink: my-native-heath
母は非常に喜んだ。何とも言われぬ淋しさを押包みながら、お茶を入れて、話をよそ事に紛らしていた。宏兒は今度初めて逢うので遠くの方へ突立って真正面からわたしを見ていた。
わたしどもはとうとう家移りのことを話した。 「あちらの家も借りることに極めて、家具もあらかた調えましたが、まだ少し足らないものもありますから、ここにある嵩張物を売払って向うで買うことにしましょう」 「それがいいよ。わたしもそう思ってね。荷拵えをした時、嵩張物は持運びに不便だから半分ばかり売ってみたがなかなかお銭にならないよ」
わたしどもはとうとう家移りのことを話した。「あちらの家も借りることに極めて、家具もあらかた調えましたが、まだ少し足らないものもありますから、ここにある嵩張物を売払って向うで買うことにしましょう」 「それがいいよ。わたしもそう思ってね。荷拵えをした時、嵩張物は持運びに不便だから半分ばかり売ってみたがなかなかお銭にならないよ」
こんな話をしたあとで母は語を継いだ。 「お前さんは久しぶりで来たんだから、本家や親類に暇乞いを済まして、それから出て行くことにしましょう」 「ええそうしましょう」 「あの閏土がね、家へ来るたんびにお前のことをきいて、ぜひ一度逢いたいと言っているんだよ」と母はにこにこして 「今度到著の日取を知らせてやったから、たぶん来るかもしれないよ」 「おお、閏土!ずいぶん昔のことですね」
こんな話をしたあとで母は語を継いだ。「お前さんは久しぶりで来たんだから、本家や親類に暇乞いを済まして、それから出て行くことにしましょう」 「ええそうしましょう」 「あの閏土がね、家へ来るたんびにお前のことをきいて、ぜひ一度逢いたいと言っているんだよ」と母はにこにこして 「今度到著の日取を知らせてやったから、たぶん来るかもしれないよ」 「おお、閏土!ずいぶん昔のことですね」
この時わたしの頭の中に一つの神さびた画面が閃き出した。深藍色の大空にかかる月はまんまろの黄金色であった。下は海辺の砂地に作られた西瓜畑で、果てしもなき碧緑の中に十一二歳の少年がぽつりと一人立っている。項には銀の輪を掛け、手には鋼鉄の叉棒を握って一疋の土竜に向って力任せに突き刺すと、土竜は身をひねって彼の跨ぐらを潜って逃げ出す。
@ -34,35 +36,35 @@ abbrlink: my-native-heath
われわれはその時、何か知らんいろんな事を話したが、ただ覚えているのは、閏土が非常にハシャいで、まだ見たことのないいろいろの物を街へ来て初めて見たとの話だった。
次の日わたしは彼に鳥をつかまえてくれと頼んだ。 「それは出来ません。大雪が降ればいいのですがね。わたしどもの沙地の上に雪が降ると、わたしは雪を掻き出して小さな一つの空地を作り、短い棒で大きな箕を支え、小米を撒きちらしておきます。小鳥が食いに来た時、わたしは遠くの方で棒の上に縛ってある縄を引くと、小鳥は箕の下へ入ってしまいます。何でも皆ありますよ。稲鶏、角鶏、※鴣「孛鳥」、105-11、藍背……」
次の日わたしは彼に鳥をつかまえてくれと頼んだ。「それは出来ません。大雪が降ればいいのですがね。わたしどもの沙地の上に雪が降ると、わたしは雪を掻き出して小さな一つの空地を作り、短い棒で大きな箕を支え、小米を撒きちらしておきます。小鳥が食いに来た時、わたしは遠くの方で棒の上に縛ってある縄を引くと、小鳥は箕の下へ入ってしまいます。何でも皆ありますよ。稲鶏、角鶏、※鴣「孛鳥」、105-11、藍背……」
そこでわたしは雪の降るのを待ちかねた。閏土はまた左のような話をした。 「今は寒くていけませんが、夏になったらわたしの処へ被入っしゃい。わたしどもは昼間海辺に貝殻取に行きます。赤いのや青いのや、鬼が見て恐れるのや、観音様の手もあります。晩にはお父さんと一緒に西瓜の見張りに行きますから、あなたも被入っしゃい」 「泥棒の見張をするのかえ」 「いいえ、旅の人が喉が渇いて一つぐらい取って食べても、家の方では泥棒の数に入れません。見張が要るのは猪、山あらし、土竜の類です。月明りの下でじっと耳を澄ましているとララと響いて来ます。土竜が瓜を噛んでるんですよ。その時あなたは叉棒を攫んでそっと行って御覧なさい」 わたしはそのいわゆる土竜というものがどんなものか、その時ちっとも知らなかった。――今でも解らない――ただわけもなく、小犬のような形で非常に猛烈のように感じた。 「彼は咬みついて来るだろうね」 「こちらには叉棒がありますからね。歩いて行って見つけ次第、あなたはそれを刺せばいい。こん畜生は馬鹿に利巧な奴で、あべこべにあなたの方へ馳け出して来て、跨の下から逃げてゆきます。あいつの毛皮は油のように滑ッこい」
そこでわたしは雪の降るのを待ちかねた。閏土はまた左のような話をした。「今は寒くていけませんが、夏になったらわたしの処へ被入っしゃい。わたしどもは昼間海辺に貝殻取に行きます。赤いのや青いのや、鬼が見て恐れるのや、観音様の手もあります。晩にはお父さんと一緒に西瓜の見張りに行きますから、あなたも被入っしゃい」 「泥棒の見張をするのかえ」 「いいえ、旅の人が喉が渇いて一つぐらい取って食べても、家の方では泥棒の数に入れません。見張が要るのは猪、山あらし、土竜の類です。月明りの下でじっと耳を澄ましているとララと響いて来ます。土竜が瓜を噛んでるんですよ。その時あなたは叉棒を攫んでそっと行って御覧なさい」 わたしはそのいわゆる土竜というものがどんなものか、その時ちっとも知らなかった。――今でも解らない――ただわけもなく、小犬のような形で非常に猛烈のように感じた。「彼は咬みついて来るだろうね」 「こちらには叉棒がありますからね。歩いて行って見つけ次第、あなたはそれを刺せばいい。こん畜生は馬鹿に利巧な奴で、あべこべにあなたの方へ馳け出して来て、跨の下から逃げてゆきます。あいつの毛皮は油のように滑ッこい」
わたしは今までこれほど多くの珍らしいことが世の中にあろうとは知らなかった。海辺にこんな五色の貝殻があったり、西瓜にこんな危険性があったり――わたしは今の先きまで西瓜は水菓子屋の店に売っているものとばかし思っていた。 「わたしどもの沙地の中には大潮の来る前に、たくさん跳ね魚が集って来て、ただそれだけが跳ね廻っています。青蛙のように二つの脚があって……」 ああ閏土の胸の中には際限もなく不思議な話が繋がっていた。それはふだんわたしどもの往来している友達の知らぬことばかりで、彼等は本当に何一つ知らなかった。閏土が海辺にいる時彼等はわたしと同じように、高塀に囲まれた屋敷の上の四角な空ばかり眺めていたのだから。
わたしは今までこれほど多くの珍らしいことが世の中にあろうとは知らなかった。海辺にこんな五色の貝殻があったり、西瓜にこんな危険性があったり――わたしは今の先きまで西瓜は水菓子屋の店に売っているものとばかし思っていた。「わたしどもの沙地の中には大潮の来る前に、たくさん跳ね魚が集って来て、ただそれだけが跳ね廻っています。青蛙のように二つの脚があって……」 ああ閏土の胸の中には際限もなく不思議な話が繋がっていた。それはふだんわたしどもの往来している友達の知らぬことばかりで、彼等は本当に何一つ知らなかった。閏土が海辺にいる時彼等はわたしと同じように、高塀に囲まれた屋敷の上の四角な空ばかり眺めていたのだから。
惜しいかな、正月は過ぎ去り、閏土は彼の郷里に帰ることになった。わたしは大哭きに哭いた。閏土もまた泣き出し、台所に隠れて出て行くまいとしたが、遂に彼の父親に引張り出された。
彼はその後父親に託けて貝殻一包と見事な鳥の毛を何本か送って寄越した。わたしの方でも一二度品物を届けてやったこともあるが、それきり顔を見たことが無い。
現在わたしの母が彼のことを持出したので、わたしのあの時の記憶が電の如くよみがえって来て、本当に自分の美しい故郷を見きわめたように覚えた。わたしは声に応じて答えた。 「そりゃ面白い。彼はどんな風です」 「あの人かえ、あの人の景気もあんまりよくないようだよ」
現在わたしの母が彼のことを持出したので、わたしのあの時の記憶が電の如くよみがえって来て、本当に自分の美しい故郷を見きわめたように覚えた。わたしは声に応じて答えた。「そりゃ面白い。彼はどんな風です」 「あの人かえ、あの人の景気もあんまりよくないようだよ」
母はそういいながら室の外を見た。 「おやまた誰か来たよ。木器買うと言っては手当り次第に持って行くんだから、わたしがちょっと見て来ましょう」
母はそういいながら室の外を見た。「おやまた誰か来たよ。木器買うと言っては手当り次第に持って行くんだから、わたしがちょっと見て来ましょう」
母が出て行くと門外の方で四五人の女の声がした。わたしは宏兒を側へ喚んで彼と話をした。字が書けるか、この家を出て行きたいと思うか、などということを訊いてみた。 「わたしどもは汽車に乗ってゆくのですか」 「汽車に乗ってゆくんだよ」 「船は?」 「まず船に乗るんだ」 「おや、こんなになったんですかね。お鬚がまあ長くなりましたこと」
母が出て行くと門外の方で四五人の女の声がした。わたしは宏兒を側へ喚んで彼と話をした。字が書けるか、この家を出て行きたいと思うか、などということを訊いてみた。「わたしどもは汽車に乗ってゆくのですか」 「汽車に乗ってゆくんだよ」 「船は?」 「まず船に乗るんだ」 「おや、こんなになったんですかね。お鬚がまあ長くなりましたこと」
一種尖ったおかしな声が突然わめき出した。
わたしは喫驚して頭を上げると、頬骨の尖った唇の薄い、五十前後の女が一人、わたしの眼の前に突立っていた。袴も無しに股引穿きの両足を踏ん張っている姿は、まるで製図器のコンパスみたいだ。
わたしはぎょっとした。 「解らないかね、わたしはお前を抱いてやったことが幾度もあるよ」
わたしはぎょっとした。「解らないかね、わたしはお前を抱いてやったことが幾度もあるよ」
わたしはいよいよ驚いたが、いい塩梅にすぐあとから母が入って来て側から 「この人は永い間外に出ていたから、みんな忘れてしまったんです。お前、覚えておいでだろうね」
とわたしの方へ向って 「これはすじ向うの楊二嫂だよ。そら豆腐屋さんの」
おおそう言われると想い出した。わたしの子供の時分、すじ向うの豆腐屋の奥に一日坐り込んでいたのがたしか楊二嫂とか言った。彼女は近処で評判の「豆腐西施」で白粉をコテコテ塗っていたが、頬骨もこんなに高くはなく、唇もこんなに薄くはなく、それにまたいつも坐っていたので、こんな分廻しのような姿勢を見るのはわたしも初めてで、その時分彼女があるためにこの豆腐屋の商売が繁盛するという噂をきいていたが、それも年齢の関係で、わたしは未だかつて感化を受けたことがないからまるきり覚えていない。ところがコンパス西施はわたしに対してはなはだ不平らしく、たちまち侮りの色を現し、さながらフランス人にしてナポレオンを知らず、亜米利加人にしてワシントンを知らざるを嘲る如く冷笑した。 「忘れたの?出世すると眼の位まで高くなるというが、本当だね」 「いえ、決してそんなことはありません、わたし……」
おおそう言われると想い出した。わたしの子供の時分、すじ向うの豆腐屋の奥に一日坐り込んでいたのがたしか楊二嫂とか言った。彼女は近処で評判の「豆腐西施」で白粉をコテコテ塗っていたが、頬骨もこんなに高くはなく、唇もこんなに薄くはなく、それにまたいつも坐っていたので、こんな分廻しのような姿勢を見るのはわたしも初めてで、その時分彼女があるためにこの豆腐屋の商売が繁盛するという噂をきいていたが、それも年齢の関係で、わたしは未だかつて感化を受けたことがないからまるきり覚えていない。ところがコンパス西施はわたしに対してはなはだ不平らしく、たちまち侮りの色を現し、さながらフランス人にしてナポレオンを知らず、亜米利加人にしてワシントンを知らざるを嘲る如く冷笑した。「忘れたの?出世すると眼の位まで高くなるというが、本当だね」 「いえ、決してそんなことはありません、わたし……」
わたしは慌てて立上がった。 「そんなら迅ちゃん、お前さんに言うがね。お前はお金持になったんだから、引越しだってなかなか御大層だ。こんな我楽多道具なんか要るもんかね。わたしに譲っておくれよ、わたしども貧乏人こそ使い道があるわよ」 「わたしは決して金持ではありません。こんなものでも売ったら何かの足しまえになるかと思って……」 「おやおやお前は結構な道台さえも捨てたという話じゃないか。それでもお金持じゃないの?お前は今三人のお妾さんがあって、外に出る時には八人舁きの大轎に乗って、それでもお金持じゃないの?ホホ何と被仰ろうが、私を瞞すことは出来ないよ」
わたしは慌てて立上がった。「そんなら迅ちゃん、お前さんに言うがね。お前はお金持になったんだから、引越しだってなかなか御大層だ。こんな我楽多道具なんか要るもんかね。わたしに譲っておくれよ、わたしども貧乏人こそ使い道があるわよ」 「わたしは決して金持ではありません。こんなものでも売ったら何かの足しまえになるかと思って……」 「おやおやお前は結構な道台さえも捨てたという話じゃないか。それでもお金持じゃないの?お前は今三人のお妾さんがあって、外に出る時には八人舁きの大轎に乗って、それでもお金持じゃないの?ホホ何と被仰ろうが、私を瞞すことは出来ないよ」
わたしは話のしようがなくなって口を噤んで立っていると 「全くね、お金があればあるほど塵ッ葉一つ出すのはいやだ。塵ッ葉一つ出さなければますますお金が溜るわけだ」
@ -76,23 +78,23 @@ abbrlink: my-native-heath
とまず口を切って、続いて連珠の如く湧き出す話、角鶏、飛魚、貝殻、土竜……けれど結局何かに弾かれたような工合になって、ただ頭の中をぐるぐる廻っているだけで口外へ吐き出すことが出来ない。
彼はのそりと立っていた。顔の上には喜びと淋しさを現わし、唇は動かしているが声が出ない。彼の態度は結局敬い奉るのであった。 「旦那様」
彼はのそりと立っていた。顔の上には喜びと淋しさを現わし、唇は動かしているが声が出ない。彼の態度は結局敬い奉るのであった。「旦那様」
と一つハッキリ言った。わたしはぞっとして身顫いが出そうになった。なるほどわたしどもの間にはもはや悲しむべき隔てが出来たのかと思うと、わたしはもう話も出来ない。
彼は頭を後ろに向け 「水生や、旦那様にお辞儀をしなさい」
と背中に躱れている子供を引出した。これはちょうど三十年前の閏土と同じような者であるが、それよりずっと痩せ黄ばんで頸のまわりに銀の輪がない。 「これは五番目の倅ですが、人様の前に出たことがありませんから、はにかんで困ります」
と背中に躱れている子供を引出した。これはちょうど三十年前の閏土と同じような者であるが、それよりずっと痩せ黄ばんで頸のまわりに銀の輪がない。「これは五番目の倅ですが、人様の前に出たことがありませんから、はにかんで困ります」
母は宏兒を連れて二階から下りて来た。大方われわれの話声を聞きつけて来たのだろう。閏土は丁寧に頭を低げて 「大奥様、お手紙を有難く頂戴致しました。わたしは旦那様がお帰りになると聞いて、何しろハアこんな嬉しいことは御座いません」 「まあお前はなぜそんな遠慮深くしているの、先にはまるで兄弟のようにしていたじゃないか。やっぱり昔のように迅ちゃんとお言いよ」
母親はいい機嫌であった。 「奥さん、今はそんなわけにはゆきません。あの時分は子供のことで何もかも解りませんでしたが」
母親はいい機嫌であった。「奥さん、今はそんなわけにはゆきません。あの時分は子供のことで何もかも解りませんでしたが」
閏土はそう言いながら子供を前に引出してお辞儀をさせようとしたが、子供は羞しがって背中にこびりついて離れない。 「その子は水生だね。五番目かえ。みんなうぶだから懼がるのは当前だよ。宏兒がちょうどいい相手だ。さあお前さん達は向うへ行ってお遊び」
閏土はそう言いながら子供を前に引出してお辞儀をさせようとしたが、子供は羞しがって背中にこびりついて離れない。「その子は水生だね。五番目かえ。みんなうぶだから懼がるのは当前だよ。宏兒がちょうどいい相手だ。さあお前さん達は向うへ行ってお遊び」
宏兒はこの話を聞くとすぐに水生をさし招いた。水生は俄に元気づいて一緒になって馳け出して行った。母は閏土に席をすすめた。彼はしばらくうじうじして遂に席に著いた。長煙管を卓の側に寄せ掛け、一つの紙包を持出した。 「冬のことで何も御座いませんが、この青豆は家の庭で乾かしたんですから旦那様に差上げて下さい」
宏兒はこの話を聞くとすぐに水生をさし招いた。水生は俄に元気づいて一緒になって馳け出して行った。母は閏土に席をすすめた。彼はしばらくうじうじして遂に席に著いた。長煙管を卓の側に寄せ掛け、一つの紙包を持出した。「冬のことで何も御座いませんが、この青豆は家の庭で乾かしたんですから旦那様に差上げて下さい」
わたしは彼に暮向のことを訊ねると、彼は頭を揺り動かした。 「なかなか大変です。あの下の子供にも手伝わせておりますが、どうしても足りません。……世の中は始終ゴタついておりますし、……どちらを向いてもお金の費ることばかりで、方途が知れません……実りが悪いし、種物を売り出せば幾度も税金を掛けられ、元を削って売らなければ腐れるばかりです」
わたしは彼に暮向のことを訊ねると、彼は頭を揺り動かした。「なかなか大変です。あの下の子供にも手伝わせておりますが、どうしても足りません。……世の中は始終ゴタついておりますし、……どちらを向いてもお金の費ることばかりで、方途が知れません……実りが悪いし、種物を売り出せば幾度も税金を掛けられ、元を削って売らなければ腐れるばかりです」
彼はひたすら頭を振った。見ると顔の上にはたくさんの皺が刻まれているが、石像のようにまるきり動かない。たぶん苦しみを感ずるだけで表現することが出来ないのだろう。しばらく思案に沈んでいたが煙管を持出して煙草を吸った。
@ -108,11 +110,11 @@ abbrlink: my-native-heath
船はずんずん進んで行った。両岸の青山はたそがれの中に深黛色の装いを凝らし、皆連れ立って船後の梢に向って退く。
わたしは船窓に凭って外のぼんやりした景色を眺めていると、たちまち宏兒が質問を発した。 「叔父さん、わたしどもはいつここへ帰って来るんでしょうね」 「帰る?ハハハ。お前は向うに行き著きもしないのにもう帰ることを考えているのか」 「あの水生がね、自分の家へ遊びに来てくれと言っているんですよ」
わたしは船窓に凭って外のぼんやりした景色を眺めていると、たちまち宏兒が質問を発した。「叔父さん、わたしどもはいつここへ帰って来るんでしょうね」 「帰る?ハハハ。お前は向うに行き著きもしないのにもう帰ることを考えているのか」 「あの水生がね、自分の家へ遊びに来てくれと言っているんですよ」
宏兒は黒目勝ちの眼をみはってうっとりと外を眺めている。
わたしどもはうすら睡くなって来た。そこでまた閏土の話を持出した。母は語った。 「あの豆腐西施は家で荷造りを始めてから毎日きっとやって来るんだよ。きのうは灰溜の中から皿小鉢を十幾枚も拾い出し、論判の挙句、これはきっと閏土が埋めておいたに違いない、彼は灰を運ぶ時一緒に持帰る積りだろうなどと言って、この事を非常に手柄にして『犬ぢらし』を掴んでまるで飛ぶように馳け出して行ったが、あの纏足の足でよくまああんなに早く歩けたものだね」
わたしどもはうすら睡くなって来た。そこでまた閏土の話を持出した。母は語った。「あの豆腐西施は家で荷造りを始めてから毎日きっとやって来るんだよ。きのうは灰溜の中から皿小鉢を十幾枚も拾い出し、論判の挙句、これはきっと閏土が埋めておいたに違いない、彼は灰を運ぶ時一緒に持帰る積りだろうなどと言って、この事を非常に手柄にして『犬ぢらし』を掴んでまるで飛ぶように馳け出して行ったが、あの纏足の足でよくまああんなに早く歩けたものだね」
(犬ぢらしはわたしどもの村の養鶏の道具で、木盤の上に木柵を嵌め、中には餌を入れておく。鶏は嘴が長いから柵をとおして啄むことが出来る。犬は柵に鼻が閊えて食うことが出来ない。故に犬じ[#「じ」はママ]らしという)

View file

@ -1,12 +1,14 @@
---
title: Моя старая родина
published: 1921-01-10
tags: ["Лу Синь","Современная литература"]
tags:
- Лу Синь
- Современная литература
lang: ru
abbrlink: my-native-heath
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
Было очень холодно, когда после более чем двадцатилетнего отсутствия я отправился навестить свою родную пустошь, расположенную более чем в двух тысячах ли отсюда.

View file

@ -1,12 +1,14 @@
---
title: 故鄉
published: 1921-01-10
tags: ["魯迅","近代文學"]
tags:
- 魯迅
- 近代文學
lang: zh-tw
abbrlink: my-native-heath
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
我冒了嚴寒,回到相隔二千餘里,別了二十餘年的故鄉去。

View file

@ -1,12 +1,14 @@
---
title: 故乡
published: 1921-01-10
tags: ["鲁迅","近代文学"]
tags:
- 鲁迅
- 近代文学
lang: zh
abbrlink: my-native-heath
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/03.webp)
我冒了严寒,回到相隔二千馀里,别了二十馀年的故乡去。
@ -24,15 +26,15 @@ abbrlink: my-native-heath
但我们终于谈到搬家的事。我说外间的寓所已经租定了,又买了几件家具,此外须将家里所有的木器卖去,再去增添。母亲也说好,而且行李也略已齐集,木器不便搬运的,也小半卖去了,只是收不起钱来。
‘你休息一两天,去拜望亲戚本家一回,我们便可以走了。’母亲说。
“你休息一两天,去拜望亲戚本家一回,我们便可以走了。”母亲说。
‘是的。’
“是的。”
还有闰土,他每到我家来时,总问起你,很想见你一回面。我已经将你到家的大约日期通知他,他也许就要来了。
还有闰土,他每到我家来时,总问起你,很想见你一回面。我已经将你到家的大约日期通知他,他也许就要来了。
这时候,我的脑里忽然闪出一幅神异的图画来:深蓝的天空中挂着一轮金黄的圆月,下面是海边的沙地,都种着一望无际的碧绿的西瓜,其间有一个十一二岁的少年,项带银圈,手捏一柄钢叉,向一匹猹尽力的刺去,那猹却将身一扭,反从他的胯下逃走了。
这少年便是闰土。我认识他时,也不过十多岁,离现在将有三十年了;那时我的父亲还在世,家景也好,我正是一个少爷。那一年,我家是一件大祭祀的值年。这祭祀,说是三十多年才能轮到一回,所以很郑重;正月里供祖像,供品很多,祭器很讲究,拜的人也很多,祭器也很要防去。我家只有一个忙月(我们这里给人做工的分三种:整年给一定人家做工的叫长;按日给人做工的叫短工;自己也种地,只在过年过节以及收租时候来给一定的人家做工的称忙月),忙不过来,他便对父亲说,可以叫他的儿子闰土来管祭器的。
这少年便是闰土。我认识他时,也不过十多岁,离现在将有三十年了;那时我的父亲还在世,家景也好,我正是一个少爷。那一年,我家是一件大祭祀的值年。这祭祀,说是三十多年才能轮到一回,所以很郑重;正月里供祖像,供品很多,祭器很讲究,拜的人也很多,祭器也很要防去。我家只有一个忙月(我们这里给人做工的分三种:整年给一定人家做工的叫长;按日给人做工的叫短工;自己也种地,只在过年过节以及收租时候来给一定的人家做工的称忙月),忙不过来,他便对父亲说,可以叫他的儿子闰土来管祭器的。
我的父亲允许了;我也很高兴,因为我早听到闰土这名字,而且知道他和我仿佛年纪,闰月生的,五行缺土,所以他的父亲叫他闰土。他是能装弶捉小鸟雀的。
@ -42,113 +44,113 @@ abbrlink: my-native-heath
第二日,我便要他捕鸟。他说:
这不能。须大雪下了才好。我们沙地上,下了雪,我扫出一块空地来,用短棒支起一个大竹匾,撒下秕谷,看鸟雀来吃时,我远远地将缚在棒上的绳子只一拉,那鸟雀就罩在竹匾下了。什么都有:稻鸡、角鸡、鹁鸪、蓝背……’
这不能。须大雪下了才好。我们沙地上,下了雪,我扫出一块空地来,用短棒支起一个大竹匾,撒下秕谷,看鸟雀来吃时,我远远地将缚在棒上的绳子只一拉,那鸟雀就罩在竹匾下了。什么都有:稻鸡,角鸡,鹁鸪,蓝背……”
我于是又很盼望下雪。
闰土又对我说:
‘现在太冷,你夏天到我们这里来。我们日里到海边检贝壳去,红的绿的都有,鬼见怕也有,观音手也有,晚上我和爹管西瓜去,你也去。’
“现在太冷,你夏天到我们这里来。我们日里到海边捡贝壳去,红的绿的都有,鬼见怕也有,观音手也有。晚上我和爹管西瓜去,你也去。”
‘管贼么?’
“管贼么?”
‘不是。走路的人口渴了摘一个瓜吃,我们这里是不算偸的。要管的是獾猪,刺猬,猹。月亮地下,你听,啦啦的响了,猹在咬瓜了。你便捏了胡叉,轻轻地走去……’
“不是。走路的人口渴了摘一个瓜吃,我们这里是不算偷的。要管的是獾猪,刺猬,猹。月亮底下,你听,啦啦的响了,猹在咬瓜了。你便捏了胡叉,轻轻地走去……”
我那时并不知道这所谓猹的是怎么一件东西——便是现在也没有知道——只是无端的觉得状如小狗而很凶猛。
‘他不咬人么?’
“他不咬人么?”
有胡叉呢。走到了,看见猹了,你便刺。这畜生很伶俐,倒向你奔来,反从胯下窜了。他的皮毛是油一般的滑。……’
有胡叉呢。走到了,看见猹了,你便刺。这畜生很伶俐,倒向你奔来,反从胯下窜了。他的皮毛是油一般的滑……”
我素不知道天下有这许多新鲜事:海边有如许五色的贝壳;西瓜有这样危险的经历,我先前单知道他在水果里出卖罢了。
我素不知道天下有这许多新鲜事:海边有如许五色的贝壳;西瓜有这样危险的经历,我先前单知道他在水果里出卖罢了。
我们沙地里,潮汛要来的时候,就有许多跳鱼儿只是跳,都有青蛙似的两个脚。……’
我们沙地里,潮汛要来的时候,就有许多跳鱼儿只是跳,都有青蛙似的两个脚……”
阿!闰土的心里有无穷无尽的希奇的事,都是我往常的朋友所不知道的。他们不知道一些事,闰土在海边时,他们都和我一样只看见院子里高墙上的四角的天空。
可惜正月过去了,闰土须回家里去,我急得大哭,他也到厨房里,哭着不肯出门,但终于被他父亲带走了。他后来还托他的父亲带给我一包贝壳和几很好看的鸟毛,我也曾送他一两次东西,但从此没有再见面。
可惜正月过去了,闰土须回家里去,我急得大哭,他也到厨房里,哭着不肯出门,但终于被他父亲带走了。他后来还托他的父亲带给我一包贝壳和几很好看的鸟毛,我也曾送他一两次东西,但从此没有再见面。
现在我的母亲提起了他,我这儿时的记忆,忽而全都闪电似的苏生过来,似乎看到了我的美丽的故乡了。我应声说:
‘这好极!他,——怎样?……’
“这好极!他,——怎样?……”
‘他?……他景况也很不如意……’母亲说着,便向房外看,‘这些人又来了。说是买木器,顺手也就随便拿走的,我得去看看。’
“他?……他景况也很不如意……”母亲说着,便向房外看,“这些人又来了。说是买木器,顺手也就随便拿走的,我得去看看。”
母亲站起身,出去了。门外有几个女人的声音我便招宏儿走近面前,和他闲话:问他可会写字,可愿意出门。
母亲站起身,出去了。门外有几个女人的声音我便招宏儿走近面前,和他闲话:问他可会写字,可愿意出门。
‘我们坐火车去么?’
“我们坐火车去么?”
‘我们坐火车去。’
“我们坐火车去。”
‘船呢?’
“船呢?”
‘先坐船,……’
“先坐船,……”
‘哈!这模样了!胡子这么长了!’一种尖利的怪声突然大叫起来。
“哈!这模样了!胡子这么长了!”一种尖利的怪声突然大叫起来。
我吃了一吓,赶忙抬起头,却见一个凸颧骨,薄嘴唇,五十岁上下的女人站在我面前,两手搭在髀间,没有系裙,张着两脚,正像一个画图仪器里细脚伶仃的圆规。
我愕然了。
‘不认识了么?我还抱过你咧!’
“不认识了么?我还抱过你咧!”
我愈加愕然了。幸而我的母亲也就进来,从旁说:
‘他多年出门,统忘却了。你该记得罢,’便向着我说,‘这是斜对门的杨二嫂,……开豆腐店的。’
“他多年出门,统忘却了。你该记得罢,”便向着我说,“这是斜对门的杨二嫂,……开豆腐店的。”
哦,我记得了。我孩子时候,在斜对门的豆腐店里确乎终日坐着一个杨二嫂,人都叫伊‘豆腐西施’。但是擦着白粉,颧骨没有这么高,嘴唇也没有这么薄。而且终日坐着,我也从没有见过这圆规式的姿势。那时人说:因为伊,这豆腐店的买卖非常好。但这大约因为年龄的关系,我却并未蒙着一毫感化,所以竟完全忘却了。然而圆规很不平,显出鄙夷的神色,仿佛嗤笑法国人不知道拿破仑,美国人不知道华盛顿似的,冷笑说:
哦,我记得了。我孩子时候,在斜对门的豆腐店里确乎终日坐着一个杨二嫂,人都叫伊“豆腐西施”。但是擦着白粉,颧骨没有这么高,嘴唇也没有这么薄,而且终日坐着,我也从没有见过这圆规式的姿势。那时人说:因为伊,这豆腐店的买卖非常好。但这大约因为年龄的关系,我却并未蒙着一毫感化,所以竟完全忘却了。然而圆规很不平,显出鄙夷的神色,仿佛嗤笑法国人不知道拿破仑,美国人不知道华盛顿似的,冷笑说:
‘忘了?这真是贵人眼高。……’
“忘了?这真是贵人眼高……”
‘那有这事……我……’我惶恐着,站起来说。
“那有这事……我……”我惶恐着,站起来说。
那么,我对你说。迅哥儿,你阔了,搬动又笨重,你还要什么这些破烂木器,让我拿去罢。我们小户人家,用得着。
那么,我对你说。迅哥儿,你阔了,搬动又笨重,你还要什么这些破烂木器,让我拿去罢。我们小户人家,用得着。
‘我并没有阔哩。我须卖了这些,再去……’
“我并没有阔哩。我须卖了这些,再去……”
阿呀呀,你放了道台了,还说不阔?你现在有三房姨太太;出门便是八抬的大轿,还说不阔?吓,什么都瞒不过我。
阿呀呀,你放了道台了,还说不阔?你现在有三房姨太太;出门便是八抬的大轿,还说不阔?吓,什么都瞒不过我。
我知道无话可说了,便闭了口,默默的站着。
阿呀阿呀,真是愈有钱,便愈是一毫不肯放松,愈是一毫不肯放松,便愈有钱……圆规一面愤愤的回转身,一面絮絮的说,慢慢向外走,顺便将我母亲的一副手套塞在裤腰里,出去了。
阿呀阿呀,真是愈有钱,便愈是一毫不肯放松,愈是一毫不肯放松,便愈有钱……圆规一面愤愤的回转身,一面絮絮的说,慢慢向外走,顺便将我母亲的一副手套塞在裤腰里,出去了。
此后又有近处的本家和亲戚来访问我。我一面应酬,空便收拾些行李,这样的过了三四天。
此后又有近处的本家和亲戚来访问我。我一面应酬,空便收拾些行李,这样的过了三四天。
一日是天气很冷的午后,我吃过午饭,坐着喝茶,觉得外面有人进来了,便回头去看。我看时,不由的非常出惊,慌忙站起身,迎着走去。
这来的便是闰土。虽然我一见便知道是闰土,但又不是我这记忆上的闰土了。他身材增加了一倍;先前的紫色的圆脸,已经变作灰黄,而且加上了很深的皱纹;眼睛也像他父亲一样,周围都肿得通红,这我知道,在海边种地的人,终日吹着海风,大抵是这样的。他头上是一顶破毡帽,身上只一件极薄的棉衣,浑身瑟索着;手里提着一个纸包和一长烟管,那手也不是我所记得的红活圆实的手,却又粗又笨而且开裂,像是松树皮了。
这来的便是闰土。虽然我一见便知道是闰土,但又不是我这记忆上的闰土了。他身材增加了一倍;先前的紫色的圆脸,已经变作灰黄,而且加上了很深的皱纹;眼睛也像他父亲一样,周围都肿得通红,这我知道,在海边种地的人,终日吹着海风,大抵是这样的。他头上是一顶破毡帽,身上只一件极薄的棉衣,浑身瑟索着;手里提着一个纸包和一长烟管,那手也不是我所记得的红活圆实的手,却又粗又笨而且开裂,像是松树皮了。
我这时很兴奋,但不知道怎么说才好,只是说:
‘阿!闰土哥,——你来了?……’
“阿!闰土哥,——你来了?……”
我接着便有许多话,想要连珠一般涌出:角鸡、跳鱼儿、贝壳、猹,……但又总觉得被什么挡着似的。单在脑里面回旋,吐不出口外去。
我接着便有许多话,想要连珠一般涌出:角鸡,跳鱼儿,贝壳,猹,……但又总觉得被什么挡着似的,单在脑里面回旋,吐不出口外去。
他站住了,脸上现出欢喜和凄凉的神情;动着嘴唇,却没有作声。他的态度终于恭敬起来了,分明的叫道:
‘老爷!……’
“老爷!……”
我似乎打了一个寒噤;我就知道,我们之间已经隔了一层可悲的厚障壁了。我也说不出话。
他回过头去说:‘水生,给老爷磕头。’便拖出躱在背后的孩子来,这正是一个二十年前的闰土,只是黄瘦些,颈子上没有银圈罢了。‘这是第五个孩子,没有见过世面,躱躱闪闪。……’
他回过头去说,“水生,给老爷磕头。”便拖出躲在背后的孩子来,这正是一个廿年前的闰土,只是黄瘦些,颈子上没有银圈罢了。“这是第五个孩子,没有见过世面,躲躲闪闪……”
母亲和宏儿下楼来了,他们大约也听到了声音。
‘老太太。信是早收到了。我实在喜欢的了不得,知道老爷回来……’闰土说。
“老太太。信是早收到了。我实在喜欢的不得了,知道老爷回来……”闰土说。
‘阿,你怎的这样客气起来。你们先前不是哥弟称呼么?还是照旧:迅哥儿。’母亲高兴的说。
“阿,你怎的这样客气起来。你们先前不是哥弟称呼么?还是照旧:迅哥儿。”母亲高兴的说。
‘阿呀,老太太真是……这成什么规矩。那时是孩子,不懂事……’闰土说着,又叫水生上来打拱,那孩子却害羞,紧紧的只贴在他背后。
“阿呀,老太太真是……这成什么规矩。那时是孩子,不懂事……”闰土说着,又叫水生上来打拱,那孩子却害羞,紧紧的只贴在他背后。
‘他就是水生?第五个?都是生人,怕生也难怪的;还是宏儿和他去走走。’母亲说。
“他就是水生?第五个?都是生人,怕生也难怪的;还是宏儿和他去走走。”母亲说。
宏儿听得这话,便来招水生,水生却松松爽爽同他一路出去了。母亲叫闰土坐,他迟疑了一回,终于就了坐,将长烟管靠在桌旁,递过纸包来,说:
‘冬天没有什么东西了。这一点干青豆倒是自家晒在那里的,请老爷……’
“冬天没有什么东西了。这一点干青豆倒是自家晒在那里的,请老爷……”
我问问他的景况。他只是摇头。
非常难。第六个孩子也会帮忙了,却总是吃不够……又不太平……什么地方都要钱,没有规……收成又坏。种出东西来,挑去卖,总要捐几回钱,折了本;不去卖,又只能烂掉。……’
非常难。第六个孩子也会帮忙了,却总是吃不够……又不太平……什么地方都要钱,没有规……收成又坏。种出东西来,挑去卖,总要捐几回钱,折了本;不去卖,又只能烂掉……”
他只是摇头;脸上虽然刻着许多皱纹,却全然不动,仿佛石像一般。他大约只是觉得苦,却又形容不出,沉默了片时,便拿起烟管来默默的吸烟了。
@ -166,22 +168,22 @@ abbrlink: my-native-heath
宏儿和我靠着船窗,同看外面模糊的风景,他忽然问道:
‘大伯!我们甚么时候回来?’
“大伯!我们什么时候回来?”
‘回来?你怎么还没有走就想回来了。’
“回来?你怎么还没有走就想回来了。”
‘可是,水生约我到他家玩去咧……’他睁着大的黑眼睛,痴痴的想。
“可是,水生约我到他家玩去咧……”他睁着大的黑眼睛,痴痴的想。
我和母亲也都有些惘然,于是又提起闰土来。母亲说那豆腐西施的杨二嫂,自从我家收拾行李以来,本是每日必到的,前天伊在灰堆里,掏出十多个碗碟来,议论之后,便定说是闰土埋着的,他可以在运灰的时候,一齐搬回家里去;杨二嫂发见了这件事,自己很以为功,便拿了那狗气杀(这是我们这里养鸡的器具,木盘上面有着栅栏,内盛食料,鸡可以伸进颈子去啄,狗却不能,只能看着气死),飞也似的跑了,亏伊装着这么高的小脚,竟跑得这样快。
我和母亲也都有些惘然,于是又提起闰土来。母亲说那豆腐西施的杨二嫂,自从我家收拾行李以来,本是每日必到的,前天伊在灰堆里,掏出十多个碗碟来,议论之后,便定说是闰土埋着的,他可以在运灰的时候,一齐搬回家里去;杨二嫂发见了这件事,自己很以为功,便拿了那狗气杀(这是我们这里养鸡的器具,木盘上面有着栅栏,内盛食料,鸡可以伸进颈子去啄,狗却不能,只能看着气死),飞也似的跑了,亏伊装着这么高的小脚,竟跑得这样快。
老屋离我愈远了;故乡的山水也都渐渐远离了我,但我却并不感到怎样的留恋。我只觉得我四面有看不见的高墙,将我隔成孤身,使我非常气闷;那西瓜地上的银项圈的小英雄的影,我本来十分清楚,现在却忽地模糊了,又使我非常的悲哀。
老屋离我愈远了;故乡的山水也都渐渐远离了我,但我却并不感到怎样的留恋。我只觉得我四面有看不见的高墙,将我隔成孤身,使我非常气闷;那西瓜地上的银项圈的小英雄的影,我本来十分清楚,现在却忽地模糊了,又使我非常的悲哀。
母亲和宏儿都睡着了。
我躺着,听船底潺潺的水声,知道我在走我的路我想:我竟与闰土隔绝到这地步了,但我们的后辈还是一气,宏儿不是正在想念水生么。我希望他们不再像我,又大家隔膜起来……然而我又不愿意他们因为要一气,都如我的辛苦展转而生活,也不愿意他们都如闰土的辛苦麻木而生活,也不愿意都如别人的辛苦恣睢而生活。他们应该有新的生活,为我们所未经生活过的。
我躺着,听船底潺潺的水声,知道我在走我的路我想:我竟与闰土隔绝到这地步了,但我们的后辈还是一气,宏儿不是正在想念水生么。我希望他们不再像我,又大家隔膜起来……然而我又不愿意他们因为要一气,都如我的辛苦展转而生活,也不愿意他们都如闰土的辛苦麻木而生活,也不愿意都如别人的辛苦恣睢而生活。他们应该有新的生活,为我们所未经生活过的。
我想到希望,忽然害怕起来了。闰土要香炉和烛台的时候,我还暗地里笑他,以为他总是崇拜偶像,什么时候都不忘却。现在我所谓希望,不也是我自己手制的偶像么?只是他的愿望切近,我的愿望茫远罢了。
我在朦胧中,眼前展开一片海边碧绿的沙地来,上面深蓝的天空中挂着一轮金黄的圆月。我想:希望本是无所谓有,无所谓无的。这正如地上的路,其实地上本没有路;走的人多了,也便成了路。
我在朦胧中,眼前展开一片海边碧绿的沙地来,上面深蓝的天空中挂着一轮金黄的圆月。我想:希望本是无所谓有,无所谓无的。这正如地上的路;其实地上本没有路,走的人多了,也便成了路。
一九二一年一月。

View file

@ -1,12 +1,14 @@
---
title: Rashomon
published: 1915-11-05
tags: ["Ryunosuke Akutagawa","Modern Literature"]
tags:
- Ryunosuke Akutagawa
- Modern Literature
lang: en
abbrlink: rashomon
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
It happened in the evening of one day. There was a retainer who was waiting for the rain under Rashomon.
@ -14,7 +16,7 @@ There was no one else under the wide door except this man. Only a cricket was pe
The reason for this is that in the past two or three years, Kyoto has experienced a series of disasters such as earthquakes, tornadoes, fires, famines, etc., so the capital has become particularly desolate. According to old records, the Buddha statues and Buddhist instruments were broken into pieces, and the pieces of wood covered with lacquer, gold and silver foil were piled on the roadside and sold as firewood. Given the situation in the capital, naturally no one would care about repairing Rashomon Gate or anything like that. Foxes and robbers took advantage of the desolation to live there, and eventually they even developed the habit of dumping ownerless corpses on the door. As soon as the sun went down, people felt the gloomy air and no one walked near this door anymore.
Instead, many crows gathered towards this place from nowhere. Looking during the day, there were countless crows circling around the highest ridge, crying and dancing. When the sky above the gate was illuminated by the setting sun and turned red, it looked as if sesame seeds were scattered there, and was particularly clear. Needless to say, the crows came to eat the flesh of the dead body on the door. ——But today, perhaps because it was too late, not a single one was seen. I saw stone steps that were about to collapse, with weeds growing in the cracks, and white spots of crow droppings sticking to them. The servant sat on the top of the seven steps, wearing his well-worn red-green jacket, and stared blankly at the rain, irritated by a large pimple on his right cheek.
Instead, many crows gathered towards this place from nowhere. Looking during the day, there were countless crows circling around the highest ridge, crying and dancing. When the sky above the gate was illuminated by the setting sun and turned red, it looked as if sesame seeds were scattered there, and was particularly clear. Needless to say, the crows came to eat the flesh of the dead body on the door. But today, perhaps because it was too late, not a single one was seen. I saw stone steps that were about to collapse, with weeds growing in the cracks, and white spots of crow droppings sticking to them. The servant sat on the top of the seven steps, wearing his well-worn red-green jacket, and stared blankly at the rain, irritated by a large pimple on his right cheek.
The author has already written that "the family will wait until the rain stops." However, after the rain stopped, the general had no idea what to do. Under normal circumstances, it would naturally return to its owner's home. But he had been sent away from this master four or five days ago. As mentioned above, Kyoto was in a very declining state at that time; now that this family was dismissing its master, who had served it for many years, was actually just a small aftermath of this decline. So instead of saying "the family general waited for the rain to stop", it would be more appropriate to say "the family general who was caught in the rain had nowhere to go and was at a loss as to what to do". Moreover, today's weather has a great impact on the sentimentality of this Heian period family general. The rain started at 5 p.m. and didn't seem to have stopped by 5 p.m. At this time, the family general first thought about what to do for tomorrow's work. In fact, he was holding on to the thought of being unsure about what to do for something that he couldn't do. At the same time, he listened to the sound of rain hitting the Suzaku Road.
@ -38,7 +40,7 @@ Only then did the guard notice a man squatting among the dead bodies. She was a
The guard was so moved by six parts of terror and four parts of curiosity that he almost forgot to breathe. To borrow the words of an old reporter, it feels like "Mao Dai" has been raised. Then the old woman inserted the pine torch into the crack of the floor, reached out to the dead body she had been eyeing earlier, and began to pull out the long hair one by one, just like a mother monkey catching lice for her child. The hair also seemed to be pulled out casually.
As the hair was pulled out one by one, the fear in the general's heart gradually disappeared. At the same time, hatred for the old woman gradually arose. ——No, to say “towards this old woman” might be a grammatical error; it would be better to say that my aversion to all evil grew stronger little by little. At this time, if someone asked the general the question that the man had thought about before, "Starve to death or become a robber?", the general would probably choose the one who starved to death without any regrets. This man's evil heart, like the torch that the old woman inserted into the cracks in the floor, was burning vigorously until it had come to this.
As the hair was pulled out one by one, the fear in the general's heart gradually disappeared. At the same time, hatred for the old woman gradually arose. — No, to say "towards this old woman" might be a grammatical error; it would be better to say that my aversion to all evil grew stronger little by little. At this time, if someone asked the general the question that the man had thought about before, "Starve to death or become a robber?", the general would probably choose the one who starved to death without any regrets. This man's evil heart, like the torch that the old woman inserted into the cracks in the floor, was burning vigorously until it had come to this.
The general at home naturally had no idea why the old woman pulled out the dead man's hair. So, speaking "reasonably", we still don't know whether it is good or evil. But from the perspective of the retainer, pulling out the hair of a dead person on top of Rashomon on such a rainy night was an unforgivable evil. Needless to say, his previous intention to become a robber was naturally forgotten at home.
@ -80,4 +82,4 @@ The servant quickly stripped off the old woman's clothes, and kicked the old wom
It was not long ago that the old woman, who seemed to be temporarily dead, struggled to raise her naked body from among the corpses. She uttered a nagging, groaning sound and, using the light of the still burning fire, crawled to the stairs. And from here hung short white hair, peeking under the door. Outside, there was only pitch-black night.
No one knew the whereabouts of the family general.
No one knew the whereabouts of the family general.

View file

@ -1,12 +1,14 @@
---
title: Rashōmon
published: 1915-11-05
tags: ["Ryunosuke Akutagawa","Literatura Moderna"]
tags:
- Ryunosuke Akutagawa
- Literatura Moderna
lang: es
abbrlink: rashomon
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
Ocurrió al anochecer de un día. Había un sirviente que estaba esperando la lluvia bajo Rashomon.
@ -80,4 +82,4 @@ El sirviente rápidamente le quitó la ropa a la anciana y le dio una patada vio
No hace mucho tiempo, la anciana, que parecía muerta temporalmente, luchaba por levantar su cuerpo desnudo de entre los cadáveres. Ella emitió un sonido molesto y quejumbroso y, aprovechando la luz del fuego que aún ardía, se arrastró hasta las escaleras. Y desde allí colgaba un pelo corto y blanco que se asomaba por debajo de la puerta. Afuera solo había una noche completamente oscura.
Nadie sabía el paradero del general de la familia.
Nadie sabía el paradero del general de la familia.

View file

@ -1,12 +1,14 @@
---
title: 羅生門
published: 1915-11-05
tags: ["芥川龍之介","きんだいぶんがく"]
tags:
- 芥川龍之介
- きんだいぶんがく
lang: ja
abbrlink: rashomon
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
或日の暮方の事である。一人の下人が、羅生門の下で雨やみを待つてゐた。

View file

@ -1,12 +1,14 @@
---
title: Расёмон
published: 1915-11-05
tags: ["Рюноскэ Акутагава","Современная литература"]
tags:
- Рюноскэ Акутагава
- Современная литература
lang: ru
abbrlink: rashomon
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
Это произошло вечером одного дня. Под Расёмоном находился слуга, ожидавший дождя.
@ -14,7 +16,7 @@ abbrlink: rashomon
Причина этого в том, что за последние два-три года Киото пережил ряд бедствий, таких как землетрясения, торнадо, пожары, голод и т. д., из-за чего столица стала особенно безлюдной. Согласно старым записям, статуи Будды и буддийские инструменты были разбиты на куски, а куски дерева, покрытые лаком, золотой и серебряной фольгой, были сложены на обочине дороги и проданы как дрова. Учитывая ситуацию в столице, естественно, никто не будет заботиться о ремонте ворот Расёмон или чем-то подобном. Запустением здесь воспользовались лисы и грабители, которые со временем даже взяли себе за привычку подбрасывать к двери бесхозные трупы. Как только солнце зашло, люди почувствовали мрачный воздух, и больше никто не ходил возле этой двери.
Вместо этого к этому месту словно из ниоткуда слетелось множество ворон. Днем можно было увидеть бесчисленное множество ворон, кружащих над самым высоким хребтом, кричащих и танцующих. Когда небо над воротами освещалось заходящим солнцем и становилось красным, создавалось впечатление, будто там рассыпаны семена кунжута, и оно становилось особенно ясным. Само собой разумеется, вороны прилетели, чтобы полакомиться плотью мертвого тела на двери. —Но сегодня, возможно, потому, что было слишком поздно, не было видно ни одного. Я видел каменные ступени, которые вот-вот должны были рухнуть, в трещинах которых росли сорняки, а на них виднелись белые пятна вороньего помета. Слуга сидел на верхней из семи ступенек, одетый в свою поношенную красно-зеленую куртку, и тупо смотрел на дождь, раздраженный большим прыщом на правой щеке.
Вместо этого к этому месту словно из ниоткуда слетелось множество ворон. Днем можно было увидеть бесчисленное множество ворон, кружащих над самым высоким хребтом, кричащих и танцующих. Когда небо над воротами освещалось заходящим солнцем и становилось красным, создавалось впечатление, будто там рассыпаны семена кунжута, и оно становилось особенно ясным. Само собой разумеется, вороны прилетели, чтобы полакомиться плотью мертвого тела на двери. — Но сегодня, возможно, потому, что было слишком поздно, не было видно ни одного. Я видел каменные ступени, которые вот-вот должны были рухнуть, в трещинах которых росли сорняки, а на них виднелись белые пятна вороньего помета. Слуга сидел на верхней из семи ступенек, одетый в свою поношенную красно-зеленую куртку, и тупо смотрел на дождь, раздраженный большим прыщом на правой щеке.
Автор уже написал, что «семья подождет, пока закончится дождь». Однако после того, как дождь прекратился, генерал не имел ни малейшего представления, что делать. При нормальных обстоятельствах он естественным образом вернулся бы в дом своего хозяина. Но его отослали от этого хозяина четыре или пять дней назад. Как уже упоминалось выше, в то время Киото находился в очень плачевном состоянии; теперь, когда эта семья уволила своего хозяина, служившего ей много лет, это было лишь небольшим последствием этого упадка. Поэтому вместо того, чтобы говорить «семейный генерал ждал, пока закончится дождь», было бы уместнее сказать «семейный генерал, попавший под дождь, не имел возможности куда-либо идти и не знал, что делать». Более того, сегодняшняя погода оказывает большое влияние на сентиментальность этого генерала семьи периода Хэйан. Дождь начался в 5 часов вечера и, похоже, не прекратился до 5 часов вечера. В это время семейный генерал первым делом подумал о том, что делать с завтрашней работой. На самом деле, он держался за мысль о том, что не уверен, что делать с чем-то, что он не может сделать. В то же время он слушал звук дождя, бьющего по дороге Сузаку.
@ -80,4 +82,4 @@ abbrlink: rashomon
Не так давно старая женщина, которая, казалось, временно умерла, с трудом подняла свое обнаженное тело из-под трупов. Она издала пронзительный стон и, используя свет все еще горящего огня, поползла к лестнице. И отсюда свисали короткие белые волосы, выглядывая из-под двери. Снаружи была только кромешная тьма.
Никто не знал местонахождения генерала семьи.
Никто не знал местонахождения генерала семьи.

View file

@ -1,12 +1,14 @@
---
title: 羅生門
published: 1915-11-05
tags: ["芥川龍之介","近代文學"]
tags:
- 芥川龍之介
- 近代文學
lang: zh-tw
abbrlink: rashomon
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
是一日的傍晚的事。有一個家將,在羅生門下待著雨住。
@ -14,7 +16,7 @@ abbrlink: rashomon
要說這緣故,就因為這二三年來,京都是接連的起了地動,旋風,大火,饑饉等等的災變,所以都中便格外的荒涼了。據舊記說,還將佛象和佛具打碎了,那些帶著丹漆,帶著金銀箔的木塊,都堆在路旁當柴賣。都中既是這情形,修理羅生門之類的事,自然再沒有人過問了。於是趁了這荒涼的好機會,狐狸來住,強盜來住;到後來,且至於生出將無主的死屍棄在這門上的習慣來。於是太陽一落,人們便都覺得陰氣,誰也不再在這門的附近走。
反而許多烏鴉,不知從那裡都聚向這地方。白晝一望,這鴉是不知多少匹的轉著圓圈,繞了最高的鴟吻,啼著飛舞。一到這門上的天空被夕照映得通紅的時候,這便彷彿撒著胡麻似的,尤其看得分明。不消說,這些烏鴉是因為要啄食那門上的死人的肉而來的了。 ——但在今日,或者因為時刻太晚了罷,卻一匹也沒有見。只見處處將要崩裂的,那裂縫中生出長的野草的石階上面,老鴉糞粘得點點的發白。家將將那洗舊的紅青襖子的臀部,坐在七級階的最上級,惱著那右頰上發出來的一顆大的面皰,惘惘然的看著雨下。
反而許多烏鴉,不知從那裡都聚向這地方。白晝一望,這鴉是不知多少匹的轉著圓圈,繞了最高的鴟吻,啼著飛舞。一到這門上的天空被夕照映得通紅的時候,這便彷彿撒著胡麻似的,尤其看得分明。不消說,這些烏鴉是因為要啄食那門上的死人的肉而來的了。——但在今日,或者因為時刻太晚了罷,卻一匹也沒有見。只見處處將要崩裂的,那裂縫中生出長的野草的石階上面,老鴉糞粘得點點的發白。家將將那洗舊的紅青襖子的臀部,坐在七級階的最上級,惱著那右頰上發出來的一顆大的面皰,惘惘然的看著雨下。
著者在先,已寫道「家將待著雨住」了。然而這家將便在雨住之後,卻也並沒有怎麼辦的方法。若在平時,自然是回到主人的家裡去。但從這主人,已經在四五日之前將他遣散了。上文也說過,那時的京都是非常之衰微了;現在這家將從那伺候多年的主人給他遣散,其實也只是這衰微的一個小小的餘波。所以與其說「家將待著雨住」,還不如說「遇雨的家將,沒有可去的地方,正在無法可想」,倒是愜當的。況且今日的天色,很影響到這平安朝家將的 Sentimentalisme 上去。從申未下開首的雨,到酉時還沒有停止模樣。這時候,家將就首先想著那明天的活計怎麼辦——說起來,便是抱著對於沒法辦的事,要想怎麼辦的一種毫無把握的思想,一面又並不聽而自聽著那從先前便打著朱雀大路的雨聲。
@ -38,7 +40,7 @@ abbrlink: rashomon
家將被六分的恐怖和四分的好奇心所動了,幾於暫時忘卻了呼吸。倘借了舊記的記者的話來說,便是覺得「毛戴」起來了。隨後那老嫗,將鬆明插在樓板的縫中,向先前看定的死屍伸下手去,正如母猴給猴兒捉蝨一般,一根一根的便拔那長頭髮。頭髮也似乎隨手的拔了下來。
那頭髮一根一根的拔了下來時,家將的心裡,恐怖也一點一點的消去了。而且同時,對於這老嫗的憎惡,也漸漸的發動了。 ——不,說是「對於這老嫗」,或者有些語病;倒不如說,對於一切惡的反感,一點一點的強盛起來了。這時候,倘有人向了這家將,提出這人先前在門下面所想的「餓死呢還是做強盜呢」這一個問題來,大約這家將是,便毫無留戀,揀了餓死的了。這人的惡惡之心,宛如那老嫗插在樓板縫中的松明一般,蓬蓬勃勃的燃燒上來,已經到如此。
那頭髮一根一根的拔了下來時,家將的心裡,恐怖也一點一點的消去了。而且同時,對於這老嫗的憎惡,也漸漸的發動了。——不,說是「對於這老嫗」,或者有些語病;倒不如說,對於一切惡的反感,一點一點的強盛起來了。這時候,倘有人向了這家將,提出這人先前在門下面所想的「餓死呢還是做強盜呢」這一個問題來,大約這家將是,便毫無留戀,揀了餓死的了。這人的惡惡之心,宛如那老嫗插在樓板縫中的松明一般,蓬蓬勃勃的燃燒上來,已經到如此。
那老嫗為什麼拔死人的頭髮,在家將自然是不知道的。所以照「合理的」的說,是善是惡,也還沒有知道應該屬於那—面。但由家將看來,在這陰雨的夜間,在這羅生門的上面,拔取死人的頭髮,即此便已經是無可寬恕的惡。不消說,自己先前想做強盜的事,在家將自然也早經忘卻了。
@ -46,7 +48,7 @@ abbrlink: rashomon
老嫗一瞥見家將,簡直像被弩機彈著似的,直跳起來。
「呔,那裡走!
「呔,那裡走
家將攔住了那老嫗絆著死屍踉蹌想走的逃路,這樣罵。老嫗沖開了家將,還想奔逃。家將卻又不放伊走,重複推了回來了。暫時之間,默然的叉著。然而勝負之數,是早就知道了的。家將終於抓住了老嫗的臂膊,硬將伊捻倒了。是只剩著皮骨,宛然雞腳一般的臂膊。

View file

@ -1,12 +1,14 @@
---
title: 罗生门
published: 1915-11-05
tags: ["芥川龙之介","近代文学"]
tags:
- 芥川龙之介
- 近代文学
lang: zh
abbrlink: rashomon
---
![Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
![_Here's the description of the picture](https://image.radishzz.cc/picsmaller/06.webp)
是一日的傍晚的事。有一个家将,在罗生门下待著雨住。
@ -14,7 +16,7 @@ abbrlink: rashomon
要说这缘故,就因为这二三年来,京都是接连的起了地动,旋风,大火,饥馑等等的灾变,所以都中便格外的荒凉了。据旧记说,还将佛象和佛具打碎了,那些带著丹漆,带著金银箔的木块,都堆在路旁当柴卖。都中既是这情形,修理罗生门之类的事,自然再没有人过问了。于是趁了这荒凉的好机会,狐狸来住,强盗来住;到后来,且至于生出将无主的死尸弃在这门上的习惯来。于是太阳一落,人们便都觉得阴气,谁也不再在这门的附近走。
反而许多乌鸦,不知从那里都聚向这地方。白昼一望,这鸦是不知多少匹的转著圆圈,绕了最高的鸱吻,啼著飞舞。一到这门上的天空被夕照映得通红的时候,这便仿佛撒著胡麻似的,尤其看得分明。不消说,这些乌鸦是因为要啄食那门上的死人的肉而来的了。 ——但在今日,或者因为时刻太晚了罢,却一匹也没有见。只见处处将要崩裂的,那裂缝中生出长的野草的石阶上面,老鸦粪粘得点点的发白。家将将那洗旧的红青袄子的臀部,坐在七级阶的最上级,恼著那右颊上发出来的一颗大的面疱,惘惘然的看著雨下。
反而许多乌鸦,不知从那里都聚向这地方。白昼一望,这鸦是不知多少匹的转著圆圈,绕了最高的鸱吻,啼著飞舞。一到这门上的天空被夕照映得通红的时候,这便仿佛撒著胡麻似的,尤其看得分明。不消说,这些乌鸦是因为要啄食那门上的死人的肉而来的了。——但在今日,或者因为时刻太晚了罢,却一匹也没有见。只见处处将要崩裂的,那裂缝中生出长的野草的石阶上面,老鸦粪粘得点点的发白。家将将那洗旧的红青袄子的臀部,坐在七级阶的最上级,恼著那右颊上发出来的一颗大的面疱,惘惘然的看著雨下。
著者在先,已写道“家将待著雨住”了。然而这家将便在雨住之后,却也并没有怎么办的方法。若在平时,自然是回到主人的家里去。但从这主人,已经在四五日之前将他遣散了。上文也说过,那时的京都是非常之衰微了;现在这家将从那伺候多年的主人给他遣散,其实也只是这衰微的一个小小的馀波。所以与其说“家将待著雨住”,还不如说“遇雨的家将,没有可去的地方,正在无法可想”,倒是惬当的。况且今日的天色,很影响到这平安朝家将的 Sentimentalisme 上去。从申未下开首的雨,到酉时还没有停止模样。这时候,家将就首先想著那明天的活计怎么办——说起来,便是抱著对于没法办的事,要想怎么办的一种毫无把握的思想,一面又并不听而自听著那从先前便打著朱雀大路的雨声。
@ -38,7 +40,7 @@ abbrlink: rashomon
家将被六分的恐怖和四分的好奇心所动了,几于暂时忘却了呼吸。倘借了旧记的记者的话来说,便是觉得“毛戴”起来了。随后那老妪,将松明插在楼板的缝中,向先前看定的死尸伸下手去,正如母猴给猴儿捉虱一般,一根一根的便拔那长头发。头发也似乎随手的拔了下来。
那头发一根一根的拔了下来时,家将的心里,恐怖也一点一点的消去了。而且同时,对于这老妪的憎恶,也渐渐的发动了。 ——不,说是“对于这老妪”,或者有些语病;倒不如说,对于一切恶的反感,一点一点的强盛起来了。这时候,倘有人向了这家将,提出这人先前在门下面所想的“饿死呢还是做强盗呢”这一个问题来,大约这家将是,便毫无留恋,拣了饿死的了。这人的恶恶之心,宛如那老妪插在楼板缝中的松明一般,蓬蓬勃勃的燃烧上来,已经到如此。
那头发一根一根的拔了下来时,家将的心里,恐怖也一点一点的消去了。而且同时,对于这老妪的憎恶,也渐渐的发动了。——不,说是“对于这老妪”,或者有些语病;倒不如说,对于一切恶的反感,一点一点的强盛起来了。这时候,倘有人向了这家将,提出这人先前在门下面所想的“饿死呢还是做强盗呢”这一个问题来,大约这家将是,便毫无留恋,拣了饿死的了。这人的恶恶之心,宛如那老妪插在楼板缝中的松明一般,蓬蓬勃勃的燃烧上来,已经到如此。
那老妪为什么拔死人的头发,在家将自然是不知道的。所以照“合理的”的说,是善是恶,也还没有知道应该属于那—面。但由家将看来,在这阴雨的夜间,在这罗生门的上面,拔取死人的头发,即此便已经是无可宽恕的恶。不消说,自己先前想做强盗的事,在家将自然也早经忘却了。
@ -46,7 +48,7 @@ abbrlink: rashomon
老妪一瞥见家将,简直像被弩机弹著似的,直跳起来。
“呔,那里走!
“呔,那里走
家将拦住了那老妪绊著死尸踉跄想走的逃路,这样骂。老妪冲开了家将,还想奔逃。家将却又不放伊走,重复推了回来了。暂时之间,默然的叉著。然而胜负之数,是早就知道了的。家将终于抓住了老妪的臂膊,硬将伊捻倒了。是只剩著皮骨,宛然鸡脚一般的臂膊。

View file

@ -0,0 +1,115 @@
---
title: Markdown Extended Features
published: 2025-04-25
tags:
- Guide
toc: false
lang: en
abbrlink: markdown-extended-features
---
Here are some extended Markdown features supported by Retypeset, including syntax examples and their stylistic effects.
## Figure Captions
To create automatic figure captions, use the standard Markdown image syntax `![alt](src)`. To hide the caption, add an underscore `_` before the `alt` text or leave the `alt` text empty.
### Syntax
```
![Image description](https://image.example.com/image-01.webp)
![_Image description](https://image.example.com/image-01.webp)
```
### Output
![Image description](https://image.radishzz.cc/image/gallery/06.webp)
![_Image description](https://image.radishzz.cc/image/gallery/06.webp)
## Github Repository Cards
To create a Github repository card, use the double colon syntax `::github{repo="owner/repo"}`. Repository data is fetched in real-time from the GitHub API after the page loads.
### Syntax
```
::github{repo="radishzzz/astro-theme-retypeset"}
```
### Output
::github{repo="radishzzz/astro-theme-retypeset"}
## Admonition
To create admonition blocks, use the GitHub syntax `> [!TYPE]` or the triple colon syntax `:::type`. Following types are supported: `note`, `tip`, `important`, `warning`, and `caution`.
### Syntax
```
> [!NOTE]
> Useful information that users should know, even when skimming content.
> [!TIP]
> Helpful advice for doing things better or more easily.
> [!IMPORTANT]
> Key information users need to know to achieve their goal.
:::warning
Urgent info that needs immediate user attention to avoid problems.
:::
:::caution
Advises about risks or negative outcomes of certain actions.
:::
:::note[YOUR CUSTOM TITLE]
This is a note with a custom title.
:::
```
### Output
> [!NOTE]
> Useful information that users should know, even when skimming content.
> [!TIP]
> Helpful advice for doing things better or more easily.
> [!IMPORTANT]
> Key information users need to know to achieve their goal.
:::warning
Urgent info that needs immediate user attention to avoid problems.
:::
:::caution
Advises about risks or negative outcomes of certain actions.
:::
:::note[YOUR CUSTOM TITLE]
This is a note with a custom title.
:::
## Videos
To embed videos, copy the embed code from YouTube or other video platforms and paste it into your markdown file. You don't need to keep the `width` and `height` parameters.
### Syntax
```html
<!-- Youtube -->
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<!-- Bilibili -->
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
```
### Output
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>

View file

@ -0,0 +1,115 @@
---
title: Características Extendidas de Markdown
published: 2025-04-25
tags:
- Guía
toc: false
lang: es
abbrlink: markdown-extended-features
---
Aquí presentamos algunas características extendidas de Markdown compatibles con Retypeset, incluyendo ejemplos de sintaxis y sus efectos estilísticos.
## Leyendas de Figuras
Para crear leyendas automáticas para figuras, utilice la sintaxis estándar de imágenes de Markdown `![alt](src)`. Para ocultar la leyenda, añada un guion bajo `_` antes del texto `alt` o deje el texto `alt` vacío.
### Sintaxis
```
![Descripción de la imagen](https://image.example.com/image-01.webp)
![_Descripción de la imagen](https://image.example.com/image-01.webp)
```
### Resultado
![Descripción de la imagen](https://image.radishzz.cc/image/gallery/06.webp)
![_Descripción de la imagen](https://image.radishzz.cc/image/gallery/06.webp)
## Tarjetas de Repositorios de Github
Para crear una tarjeta de repositorio de Github, utilice la sintaxis de doble dos puntos `::github{repo="owner/repo"}`. Los datos del repositorio se obtienen en tiempo real de la API de GitHub después de que la página se carga.
### Sintaxis
```
::github{repo="radishzzz/astro-theme-retypeset"}
```
### Resultado
::github{repo="radishzzz/astro-theme-retypeset"}
## Advertencia
Para crear bloques de advertencia, utilice la sintaxis de GitHub `> [!TYPE]` o la sintaxis de triple dos puntos `:::type`. Se admiten cinco tipos: `note`, `tip`, `important`, `warning` y `caution`.
### Sintaxis
```
> [!NOTE]
> Información útil que los usuarios deben conocer, incluso al leer por encima.
> [!TIP]
> Consejos útiles para hacer las cosas mejor o más fácilmente.
> [!IMPORTANT]
> Información clave que los usuarios necesitan saber para lograr su objetivo.
:::warning
Información urgente que requiere atención inmediata del usuario para evitar problemas.
:::
:::caution
Advierte sobre riesgos o resultados negativos de ciertas acciones.
:::
:::note[TÍTULO PERSONALIZADO]
Esta es una nota con un título personalizado.
:::
```
### Resultado
> [!NOTE]
> Información útil que los usuarios deben conocer, incluso al leer por encima.
> [!TIP]
> Consejos útiles para hacer las cosas mejor o más fácilmente.
> [!IMPORTANT]
> Información clave que los usuarios necesitan saber para lograr su objetivo.
:::warning
Información urgente que requiere atención inmediata del usuario para evitar problemas.
:::
:::caution
Advierte sobre riesgos o resultados negativos de ciertas acciones.
:::
:::note[TÍTULO PERSONALIZADO]
Esta es una nota con un título personalizado.
:::
## Videos
Para incrustar videos, copie el código de inserción de YouTube u otras plataformas de video y péguelo en su archivo markdown. No necesita mantener los parámetros `width` y `height`.
### Sintaxis
```html
<!-- Youtube -->
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<!-- Bilibili -->
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
```
### Resultado
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>

View file

@ -0,0 +1,115 @@
---
title: Markdown 拡張機能
published: 2025-04-25
tags:
- ガイド
toc: false
lang: ja
abbrlink: markdown-extended-features
---
この記事では、RetypesetテーマがサポートするMarkdown拡張機能について、構文例と効果を紹介します。
## 図のキャプション
標準のMarkdown画像構文 `![alt](src)` を使用すると、自動的に図のキャプションが生成されます。`alt` テキストの前にアンダースコア `_` を追加するか、`alt` テキストを空にすると、キャプションが非表示になります。
### 構文
```
![画像の説明](https://image.example.com/image-01.webp)
![_画像の説明](https://image.example.com/image-01.webp)
```
### 効果
![画像の説明](https://image.radishzz.cc/image/gallery/06.webp)
![_画像の説明](https://image.radishzz.cc/image/gallery/06.webp)
## Githubリポジトリカード
二重コロン構文 `::github{repo="owner/repo"}` を使用すると、Githubリポジトリカードを作成できます。ページの読み込み後、GitHub APIからリアルタイムでリポジトリデータが取得されます。
### 構文
```
::github{repo="radishzzz/astro-theme-retypeset"}
```
### 効果
::github{repo="radishzzz/astro-theme-retypeset"}
## アドモニションブロック
GitHub構文 `> [!TYPE]` または三重コロン構文 `:::type` を使用して、アドモニションブロックを作成できます。`note``tip``important``warning``caution` の5種類がサポートされています。
### 構文
```
> [!NOTE]
> 内容を流し読みする場合でも、ユーザーに知ってほしい有益な情報。
> [!TIP]
> タスクをよりスムーズに完了するために役立つオプション情報。
> [!IMPORTANT]
> タスクを完了するためにユーザーが必要とする重要な情報。
:::warning
ユーザーの即時の注意を必要とする潜在的なリスクがある重要な内容。
:::
:::caution
特定の操作によって生じる可能性のある悪影響について。
:::
:::note[カスタムタイトル]
これはカスタムタイトルの付いた注釈ブロックです。
:::
```
### 効果
> [!NOTE]
> 内容を流し読みする場合でも、ユーザーに知ってほしい有益な情報。
> [!TIP]
> タスクをよりスムーズに完了するために役立つオプション情報。
> [!IMPORTANT]
> タスクを完了するためにユーザーが必要とする重要な情報。
:::warning
ユーザーの即時の注意を必要とする潜在的なリスクがある重要な内容。
:::
:::caution
特定の操作によって生じる可能性のある悪影響について。
:::
:::note[カスタムタイトル]
これはカスタムタイトルの付いた注釈ブロックです。
:::
## 動画
YouTubeや他の動画プラットフォームから埋め込みコードを取得し、markdownファイルに貼り付けることで、動画を作成できます。`width``height`パラメータを保持する必要はありません。
### 構文
```html
<!-- Youtube -->
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<!-- Bilibili -->
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
```
### 効果
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>

View file

@ -0,0 +1,115 @@
---
title: Расширенные функции Markdown
published: 2025-04-25
tags:
- Руководство
toc: false
lang: ru
abbrlink: markdown-extended-features
---
Здесь представлены некоторые расширенные функции Markdown, поддерживаемые темой Retypeset, включая примеры синтаксиса и их стилистические эффекты.
## Подписи к изображениям
Для создания автоматических подписей к изображениям используйте стандартный синтаксис изображений Markdown `![alt](src)`. Чтобы скрыть подпись, добавьте подчёркивание `_` перед текстом `alt` или оставьте текст `alt` пустым.
### Синтаксис
```
![Описание изображения](https://image.example.com/image-01.webp)
![_Описание изображения](https://image.example.com/image-01.webp)
```
### Результат
![Описание изображения](https://image.radishzz.cc/image/gallery/06.webp)
![_Описание изображения](https://image.radishzz.cc/image/gallery/06.webp)
## Карточки репозиториев Github
Для создания карточки репозитория Github используйте синтаксис с двойным двоеточием `::github{repo="owner/repo"}`. Данные репозитория в режиме реального времени загружаются из API GitHub после загрузки страницы.
### Синтаксис
```
::github{repo="radishzzz/astro-theme-retypeset"}
```
### Результат
::github{repo="radishzzz/astro-theme-retypeset"}
## Примечания
Для создания блоков примечаний используйте синтаксис GitHub `> [!TYPE]` или синтаксис с тройным двоеточием `:::type`. Поддерживаются пять типов: `note`, `tip`, `important`, `warning` и `caution`.
### Синтаксис
```
> [!NOTE]
> Полезная информация, которую пользователи должны знать, даже при беглом просмотре.
> [!TIP]
> Полезные советы, как делать что-то лучше или проще.
> [!IMPORTANT]
> Ключевая информация, которую пользователи должны знать для достижения своей цели.
:::warning
Срочная информация, требующая немедленного внимания пользователя для предотвращения проблем.
:::
:::caution
Предупреждает о рисках или негативных последствиях определённых действий.
:::
:::note[ПОЛЬЗОВАТЕЛЬСКИЙ ЗАГОЛОВОК]
Это примечание с пользовательским заголовком.
:::
```
### Результат
> [!NOTE]
> Полезная информация, которую пользователи должны знать, даже при беглом просмотре.
> [!TIP]
> Полезные советы, как делать что-то лучше или проще.
> [!IMPORTANT]
> Ключевая информация, которую пользователи должны знать для достижения своей цели.
:::warning
Срочная информация, требующая немедленного внимания пользователя для предотвращения проблем.
:::
:::caution
Предупреждает о рисках или негативных последствиях определённых действий.
:::
:::note[ПОЛЬЗОВАТЕЛЬСКИЙ ЗАГОЛОВОК]
Это примечание с пользовательским заголовком.
:::
## Видео
Для добавления видео скопируйте код для встраивания с YouTube или другой видеоплатформы и вставьте его в markdown файл. Не нужно сохранять параметры `width` и `height`.
### Синтаксис
```html
<!-- Youtube -->
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<!-- Bilibili -->
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
```
### Результат
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>

View file

@ -0,0 +1,115 @@
---
title: Markdown 擴展功能
published: 2025-04-25
tags:
- 指南
toc: false
lang: zh-tw
abbrlink: markdown-extended-features
---
本文介紹 Retypeset 主題支援的 Markdown 擴展功能,包括語法示例與效果展示。
## 圖注
使用標準的 Markdown 圖像語法 `![alt](src)`,即可自動生成圖注。在 `alt` 前添加下劃線 `_` 或留空 `alt`,即可隱藏圖注。
### 語法
```
![圖片描述](https://image.example.com/image-01.webp)
![_圖片描述](https://image.example.com/image-01.webp)
```
### 效果
![圖片描述](https://image.radishzz.cc/image/gallery/06.webp)
![_圖片描述](https://image.radishzz.cc/image/gallery/06.webp)
## Github 倉庫卡片
使用雙冒號語法 `::github{repo="owner/repo"}`,即可創建 Github 倉庫卡片。在頁面載入後,從 GitHub API 中即時獲取倉庫數據。
### 語法
```
::github{repo="radishzzz/astro-theme-retypeset"}
```
### 效果
::github{repo="radishzzz/astro-theme-retypeset"}
## 提示塊
使用 GitHub 語法 `> [!TYPE]` 或三冒號語法 `:::type`,即可創建提示塊。支援 `note``tip``important``warning``caution` 五種類型。
### 語法
```
> [!NOTE]
> 即使快速瀏覽,也值得用戶留意的信息。
> [!TIP]
> 可選信息,幫助用戶更順利地完成任務。
> [!IMPORTANT]
> 用戶完成任務必需的關鍵信息。
:::warning
存在潛在風險,需用戶立即關注的重要內容。
:::
:::caution
某些操作可能帶來的負面影響。
:::
:::note[自定義標題]
這是一個自定義標題的提示塊。
:::
```
### 效果
> [!NOTE]
> 即使快速瀏覽,也值得用戶留意的信息。
> [!TIP]
> 可選信息,幫助用戶更順利地完成任務。
> [!IMPORTANT]
> 用戶完成任務必需的關鍵信息。
:::warning
存在潛在風險,需用戶立即關注的重要內容。
:::
:::caution
某些操作可能帶來的負面影響。
:::
:::note[自定義標題]
這是一個自定義標題的提示塊。
:::
## 視頻
從 YouTube 或其它視頻平台獲取嵌入代碼,並粘貼至 markdown 文件中,即可創建視頻。不需要保留 `width``height` 參數。
### 語法
```html
<!-- Youtube -->
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<!-- Bilibili -->
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
```
### 效果
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>

View file

@ -0,0 +1,127 @@
---
title: Markdown 扩展功能
published: 2025-04-25
tags:
- 指南
toc: false
lang: zh
abbrlink: markdown-extended-features
---
本文介绍 Retypeset 主题支持的 Markdown 扩展功能,包括语法示例与效果展示。
## 图注
使用标准的 Markdown 图像语法 `![alt](src)`,即可自动生成图注。在 `alt` 前添加下划线 `_` 或留空 `alt`,即可隐藏图注。
### 语法
```
![图片描述](https://image.example.com/image-01.webp)
![_图片描述](https://image.example.com/image-01.webp)
```
### 效果
![图片描述](https://image.radishzz.cc/image/gallery/06.webp)
![_图片描述](https://image.radishzz.cc/image/gallery/06.webp)
## Github 仓库卡片
使用双冒号语法 `::github{repo="owner/repo"}`,即可创建 Github 仓库卡片。在页面加载后,从 GitHub API 中实时获取仓库数据。
### 语法
```
::github{repo="radishzzz/astro-theme-retypeset"}
```
### 效果
::github{repo="radishzzz/astro-theme-retypeset"}
## 提示块
使用 GitHub 语法 `> [!TYPE]` 或三冒号语法 `:::type`,即可创建提示块。支持 `note``tip``important``warning``caution` 五种类型。
### 语法
```
> [!NOTE]
> 即使快速浏览,也值得用户留意的信息。
> [!TIP]
> 可选信息,帮助用户更顺利地完成任务。
> [!IMPORTANT]
> 用户完成任务必需的关键信息。
:::warning
存在潜在风险,需用户立即关注的重要内容。
:::
:::caution
某些操作可能带来的负面影响。
:::
:::note[自定义标题]
这是一个自定义标题的提示块。
:::
```
### 效果
> [!NOTE]
> 即使快速浏览,也值得用户留意的信息。
> [!TIP]
> 可选信息,帮助用户更顺利地完成任务。
> [!IMPORTANT]
> 用户完成任务必需的关键信息。
:::warning
存在潜在风险,需用户立即关注的重要内容。
:::
:::caution
某些操作可能带来的负面影响。
:::
:::note[自定义标题]
这是一个自定义标题的提示块。
:::
## 视频
从 YouTube 或其它视频平台获取嵌入代码,并粘贴至 markdown 文件中,即可创建视频。不需要保留 `width``height` 参数。
### 语法
```html
<!-- Youtube -->
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<!-- Bilibili -->
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
```
### 效果
<iframe src="https://www.youtube.com/embed/9pP0pIgP2kE?si=Rlk4C4ltaVPHXZ80" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=930327443&bvid=BV1sK4y1Z7KG&cid=329802177&p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
<!-- <details>
<summary>
我有钥匙却无门,有空间却无房间。你能进入却无法离开。我是什么?
</summary>
键盘。
</details>
<figure>
<img src="https://image.radishzz.cc/picsmaller/03.webp">
<figcaption text-center="">Node 模块检查器 - 概览</figcaption>
</figure> -->

View file

@ -2,8 +2,9 @@
title: Markdown Style Guide
published: 2025-03-08
updated: 2025-03-23
tags: ["Guide"]
pin: 1
tags:
- Guide
pin: 98
toc: false
lang: en
abbrlink: markdown-style-guide
@ -59,13 +60,15 @@ To add an image, add an exclamation mark `!`, followed by alt text in brackets `
### Syntax
```markdown
![Image Description](./full/or/relative/path/of/image)
```
![Image Description](../_images/image-01.jpeg)
![Image Description](https://image.example.com/image-01.webp)
```
### Output
![Image Description](/image-placeholder)
![Image Description](https://image.radishzz.cc/picsmaller/03.webp)
## Blockquotes
@ -109,7 +112,7 @@ To create a blockquote, add a `>` in front of a paragraph. To create a blockquot
## Tables
To add a table, use three or more hyphens `---` to create each columns header, and use pipes `|` to separate each column.
To add a table, use three or more hyphens `---` to create each column's header, and use pipes `|` to separate each column.
### Syntax
@ -223,7 +226,7 @@ To create a code block, add three backticks ```` ``` ```` at the start and end o
## Other Elements
Including `<sup>` superscript, `<sub>` subscript, `<abbr>` abbreviation, `<del>` strikethrough, `<u>` wavy underline, `<kbd>` keyboard input, and `<mark>` highlight.
Including `<sup>` superscript, `<sub>` subscript, `<abbr>` abbreviation, `<del>` strikethrough, `<u>` wavy underline, `<kbd>` keyboard input, `<mark>` highlight, and `<hr>` horizontal rule.
### Syntax
@ -241,6 +244,10 @@ 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.
Use three hyphens `---` or the `<hr>` tag to create a horizontal rule as shown below.
---
```
### Output
@ -258,3 +265,7 @@ 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.
Use three hyphens `---` or the `<hr>` tag to create a horizontal rule as shown below.
---

View file

@ -2,8 +2,9 @@
title: Guía de Estilo Markdown
published: 2025-03-08
updated: 2025-03-23
tags: ["Guía"]
pin: 1
tags:
- Guía
pin: 98
toc: false
lang: es
abbrlink: markdown-style-guide
@ -59,13 +60,15 @@ Para agregar una imagen, añada un signo de exclamación `!`, seguido de texto a
### Sintaxis
```markdown
![Descripción de la Imagen](./full/or/relative/path/of/image)
```
![Descripción de la Imagen](../_images/image-01.jpeg)
![Descripción de la Imagen](https://image.example.com/image-01.webp)
```
### Resultado
![Descripción de la Imagen](/image-placeholder)
![Descripción de la Imagen](https://image.radishzz.cc/picsmaller/03.webp)
## Citas en Bloque
@ -223,11 +226,11 @@ Para crear un bloque de código, agregue tres acentos graves ```` ``` ```` al in
## Otros Elementos
Incluyendo superíndice `<sup>`, subíndice `<sub>`, abreviatura `<abbr>`, tachado `<del>`, subrayado ondulado `<u>`, entrada de teclado `<kbd>` y resaltado `<mark>`.
Incluyendo superíndice `<sup>`, subíndice `<sub>`, abreviatura `<abbr>`, tachado `<del>`, subrayado ondulado `<u>`, entrada de teclado `<kbd>`, resaltado `<mark>` y línea horizontal `<hr>`.
### Sintaxis
```markdown
```html
H<sub>2</sub>O
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
@ -241,6 +244,10 @@ Presione <kbd>CTRL</kbd> + <kbd>ALT</kbd> + <kbd>Suprimir</kbd> para finalizar l
No hay <del>nada</del> ningún código que sea bueno o malo, pero ejecutarlo lo hace así.
La mayoría de las <mark>salamandras</mark> son nocturnas y cazan insectos, gusanos y otras criaturas pequeñas.
Use tres guiones `---` o la etiqueta `<hr>` para crear una línea horizontal como se muestra a continuación.
---
```
### Resultado
@ -258,3 +265,7 @@ Presione <kbd>CTRL</kbd> + <kbd>ALT</kbd> + <kbd>Suprimir</kbd> para finalizar l
No hay <del>nada</del> ningún código que sea bueno o malo, pero ejecutarlo lo hace así.
La mayoría de las <mark>salamandras</mark> son nocturnas y cazan insectos, gusanos y otras criaturas pequeñas.
Use tres guiones `---` o la etiqueta `<hr>` para crear una línea horizontal como se muestra a continuación.
---

View file

@ -2,8 +2,9 @@
title: Markdown スタイルガイド
published: 2025-03-08
updated: 2025-03-23
tags: ["ガイド"]
pin: 1
tags:
- ガイド
pin: 98
toc: false
lang: ja
abbrlink: markdown-style-guide
@ -59,13 +60,15 @@ abbrlink: markdown-style-guide
### 構文
```markdown
![画像の説明](./full/or/relative/path/of/image)
```
![画像の説明](../_images/image-01.jpeg)
![画像の説明](https://image.example.com/image-01.webp)
```
### 効果
![画像の説明](/image-placeholder)
![画像の説明](https://image.radishzz.cc/picsmaller/03.webp)
## 引用ブロック
@ -96,7 +99,7 @@ abbrlink: markdown-style-guide
>
> —— <cite>『秋の夜』[^1]</cite>
[^1]: [秋の夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85))は魯迅の散文詩集『野草』の最初の散文詩で、1924年に書かれました。
[^1]: [秋の夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85))は魯迅の散文詩集『野草』の最初の散文詩で、1924年に書かれました。
```
#### 効果
@ -105,7 +108,7 @@ abbrlink: markdown-style-guide
>
> —— <cite>『秋の夜』[^1]</cite>
[^1]: [秋の夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85))は魯迅の散文詩集『野草』の最初の散文詩で、1924年に書かれました。
[^1]: [秋の夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85))は魯迅の散文詩集『野草』の最初の散文詩で、1924年に書かれました。
## 表
@ -223,11 +226,11 @@ abbrlink: markdown-style-guide
## その他の要素
`<sup>` 上付き文字、`<sub>` 下付き文字、`<abbr>` 略語、`<del>` 取り消し線、`<u>` 波線、`<kbd>` キーボード入力、`<mark>` ハイライトなどが含まれます。
`<sup>` 上付き文字、`<sub>` 下付き文字、`<abbr>` 略語、`<del>` 取り消し線、`<u>` 波線、`<kbd>` キーボード入力、`<mark>` ハイライト`<hr>` 水平線などが含まれます。
### 構文
```markdown
```html
H<sub>2</sub>O
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
@ -241,6 +244,10 @@ X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
<kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>Delete</kbd> を押してセッションを終了します。
ほとんどの<mark>サンショウウオ</mark>は夜行性で、昆虫や虫などの小さな生き物を捕食します。
3つのハイフン `---` または `<hr>` タグを使用して、以下のような水平線を作成できます。
---
```
### 効果
@ -258,3 +265,7 @@ X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
<kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>Delete</kbd> を押してセッションを終了します。
ほとんどの<mark>サンショウウオ</mark>は夜行性で、昆虫や虫などの小さな生き物を捕食します。
3つのハイフン `---` または `<hr>` タグを使用して、以下のような水平線を作成できます。
---

View file

@ -2,8 +2,9 @@
title: Руководство по стилю Markdown
published: 2025-03-08
updated: 2025-03-23
tags: ["Руководство"]
pin: 1
tags:
- Руководство
pin: 98
toc: false
lang: ru
abbrlink: markdown-style-guide
@ -59,13 +60,15 @@ Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sap
### Синтаксис
```markdown
![Описание изображения](./full/or/relative/path/of/image)
```
![Описание изображения](../_images/image-01.jpeg)
![Описание изображения](https://image.example.com/image-01.webp)
```
### Результат
![Описание изображения](/image-placeholder)
![Описание изображения](https://image.radishzz.cc/picsmaller/03.webp)
## Цитаты
@ -223,11 +226,11 @@ Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sap
## Другие элементы
Включая верхний индекс `<sup>`, нижний индекс `<sub>`, аббревиатуру `<abbr>`, зачёркнутый текст `<del>`, волнистое подчёркивание `<u>`, ввод с клавиатуры `<kbd>` и выделение `<mark>`.
Включая верхний индекс `<sup>`, нижний индекс `<sub>`, аббревиатуру `<abbr>`, зачёркнутый текст `<del>`, волнистое подчёркивание `<u>`, ввод с клавиатуры `<kbd>`, выделение `<mark>` и горизонтальную линию `<hr>`.
### Синтаксис
```markdown
```html
H<sub>2</sub>O
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
@ -241,6 +244,10 @@ X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
Нет <del>ничего</del> ни хорошего, ни плохого кода, но запуск делает его таковым.
Большинство <mark>саламандр</mark> ведут ночной образ жизни и охотятся на насекомых, червей и других мелких существ.
Используйте три дефиса `---` или тег `<hr>` для создания горизонтальной линии, как показано ниже.
---
```
### Результат
@ -258,3 +265,7 @@ X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
Нет <del>ничего</del> ни хорошего, ни плохого кода, но запуск делает его таковым.
Большинство <mark>саламандр</mark> ведут ночной образ жизни и охотятся на насекомых, червей и других мелких существ.
Используйте три дефиса `---` или тег `<hr>` для создания горизонтальной линии, как показано ниже.
---

View file

@ -2,8 +2,9 @@
title: Markdown 樣式指南
published: 2025-03-08
updated: 2025-03-23
tags: ["指南"]
pin: 1
tags:
- 指南
pin: 98
toc: false
lang: zh-tw
abbrlink: markdown-style-guide
@ -59,13 +60,15 @@ abbrlink: markdown-style-guide
### 語法
```markdown
![圖片描述](./full/or/relative/path/of/image)
```
![圖片描述](../_images/image-01.jpeg)
![圖片描述](https://image.example.com/image-01.webp)
```
### 效果
![圖片描述](/image-placeholder)
![圖片描述](https://image.radishzz.cc/picsmaller/03.webp)
## 區塊引用
@ -96,7 +99,7 @@ abbrlink: markdown-style-guide
>
> —— <cite>《秋夜》[^1]</cite>
[^1]: [秋夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85)) 是魯迅散文詩集《野草》中的第一首散文詩創作於1924年。
[^1]: [秋夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85))是魯迅散文詩集《野草》中的第一首散文詩創作於1924年。
```
#### 效果
@ -105,7 +108,7 @@ abbrlink: markdown-style-guide
>
> —— <cite>《秋夜》[^1]</cite>
[^1]: [秋夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85)) 是魯迅散文詩集《野草》中的第一首散文詩創作於1924年。
[^1]: [秋夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85))是魯迅散文詩集《野草》中的第一首散文詩創作於1924年。
## 表格
@ -223,11 +226,11 @@ abbrlink: markdown-style-guide
## 其他元素
包括 `<sup>` 上標,`<sub>` 下標,`<abbr>` 縮寫,`<del>` 刪除線,`<u>` 波浪線,`<kbd>` 鍵盤輸入,`<mark>` 高亮。
包括 `<sup>` 上標,`<sub>` 下標,`<abbr>` 縮寫,`<del>` 刪除線,`<u>` 波浪線,`<kbd>` 鍵盤輸入,`<mark>` 高亮`<hr>` 分隔線
### 語法
```markdown
```html
H<sub>2</sub>O
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
@ -236,11 +239,15 @@ X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
書籍是人類進步的<del>樓梯</del>階梯。
優秀的作者總是會仔細檢查<u title="拼"></u>寫錯誤
優秀的作家總是會仔細檢查<u title="拼寫">拚寫</u>問題
按下 <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>Delete</kbd> 以結束會話。
大多數<mark>蠑螈</mark>晝伏夜出,以昆蟲、蠕蟲等小生物為食。
使用三個連字符 `---``<hr>` 標籤,即可創建如下分隔線。
---
```
### 效果
@ -258,3 +265,7 @@ X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
按下 <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>Delete</kbd> 以結束會話。
大多數<mark>蠑螈</mark>晝伏夜出,以昆蟲、蠕蟲等小生物為食。
使用三個連字符 `---``<hr>` 標籤,即可創建如下分隔線。
---

View file

@ -2,8 +2,9 @@
title: Markdown 样式指南
published: 2025-03-08
updated: 2025-03-23
tags: ["指南"]
pin: 1
tags:
- 指南
pin: 98
toc: false
lang: zh
abbrlink: markdown-style-guide
@ -59,13 +60,15 @@ abbrlink: markdown-style-guide
### 语法
```markdown
![图片描述](./full/or/relative/path/of/image)
```
![图片描述](../_images/image-01.jpeg)
![图片描述](https://image.example.com/image-01.webp)
```
### 效果
![图片描述](/image-placeholder)
![图片描述](https://image.radishzz.cc/picsmaller/03.webp)
## 块引用
@ -96,7 +99,7 @@ abbrlink: markdown-style-guide
>
> —— <cite>《秋夜》[^1]</cite>
[^1]: [秋夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85)) 是鲁迅散文诗集《野草》中的第一首散文诗创作于1924年。
[^1]: [秋夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85))是鲁迅散文诗集《野草》中的第一首散文诗创作于1924年。
```
#### 效果
@ -105,7 +108,7 @@ abbrlink: markdown-style-guide
>
> —— <cite>《秋夜》[^1]</cite>
[^1]: [秋夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85)) 是鲁迅散文诗集《野草》中的第一首散文诗创作于1924年。
[^1]: [秋夜](https://zh.wikisource.org/wiki/%E7%A7%8B%E5%A4%9C_(%E9%AD%AF%E8%BF%85))是鲁迅散文诗集《野草》中的第一首散文诗创作于1924年。
## 表格
@ -223,11 +226,11 @@ abbrlink: markdown-style-guide
## 其他元素
包括 `<sup>` 上标,`<sub>` 下标,`<abbr>` 缩写,`<del>` 删除线,`<u>` 波浪线,`<kbd>` 键盘输入,`<mark>` 高亮。
包括 `<sup>` 上标,`<sub>` 下标,`<abbr>` 缩写,`<del>` 删除线,`<u>` 波浪线,`<kbd>` 键盘输入,`<mark>` 高亮`<hr>` 分隔线
### 语法
```markdown
```html
H<sub>2</sub>O
X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
@ -236,11 +239,15 @@ X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
书籍是人类进步的<del>楼梯</del>阶梯。
优秀的作者总是会仔细检查<u title="拼"></u>写错误
优秀的作家总是会仔细检查<u title="拼写">拚写</u>问题
按下 <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>Delete</kbd> 以结束会话。
大多数<mark>蝾螈</mark>昼伏夜出,以昆虫、蠕虫等小生物为食。
使用三个连字符 `---``<hr>` 标签,即可创建如下分隔线。
---
```
### 效果
@ -259,14 +266,6 @@ X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
大多数<mark>蝾螈</mark>昼伏夜出,以昆虫、蠕虫等小生物为食。
<!-- <details>
<summary>
我有钥匙却无门,有空间却无房间。你能进入却无法离开。我是什么?
</summary>
键盘。
</details>
使用三个连字符 `---``<hr>` 标签,即可创建如下分隔线。
<figure>
<img src="https://image.radishzz.cc/picsmaller/03.webp">
<figcaption text-center="">Node 模块检查器 - 概览</figcaption>
</figure> -->
---

View file

@ -0,0 +1,85 @@
---
title: Theme Color Schemes
published: 2025-04-11
tags:
- Guide
toc: false
lang: en
abbrlink: theme-color-schemes
---
Retypeset defines theme color schemes based on the [OKLCH](https://oklch.com/) color space, with a default black, white, and gray color scheme that simulates a print style.
To meet personalization needs, I've created several color schemes for the theme. You can replace the default color scheme in [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) and **restart the development server** to preview the new color scheme.
## Scallion White
![Light mode](../_images/1-light.jpeg)
![Dark mode](../_images/1-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0.03 211.86)',
secondary: 'oklch(0.40 0.03 211.86)',
background: 'oklch(0.99 0.0039 106.47)',
},
dark: {
primary: 'oklch(0.92 0.0015 106.47)',
secondary: 'oklch(0.79 0.0015 106.47)',
background: 'oklch(0.24 0.0039 106.47)',
},
```
## Raven Teal
![Light mode](../_images/2-light.jpeg)
![Dark mode](../_images/2-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.0172 280.05)',
secondary: 'oklch(0.40 0.0172 280.05)',
background: 'oklch(0.98 0.0172 280.05)',
},
dark: {
primary: 'oklch(0.92 0.0172 280.05)',
secondary: 'oklch(0.79 0.0172 280.05)',
background: 'oklch(0.24 0.0172 280.05)',
},
```
## Ink Blue
![Light mode](../_images/4-light.jpeg)
![Dark mode](../_images/4-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.053 261.24)',
secondary: 'oklch(0.39 0.053 261.24)',
background: 'oklch(1 0 0)',
},
dark: {
primary: 'oklch(0.92 0 0)',
secondary: 'oklch(0.79 0 0)',
background: 'oklch(0.24 0.016 265.21)',
},
```
## Ecru
![Light mode](../_images/3-light.jpeg)
![Dark mode](../_images/3-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0 0)',
secondary: 'oklch(0.41 0 0)',
background: 'oklch(0.95 0.0237 59.39)',
},
dark: {
primary: 'oklch(0.93 0.019 59.39)',
secondary: 'oklch(0.80 0.017 59.39)',
background: 'oklch(0.23 0 0)',
},
```

View file

@ -0,0 +1,85 @@
---
title: Esquemas de Color del Tema
published: 2025-04-11
tags:
- Guía
toc: false
lang: es
abbrlink: theme-color-schemes
---
Retypeset define los esquemas de color del tema basados en el espacio de color [OKLCH](https://oklch.com/), con un esquema predeterminado de colores negro, blanco y gris que simula un estilo de impresión.
Para satisfacer las necesidades de personalización, he creado varios esquemas de colores para el tema. Puedes reemplazar el esquema de colores predeterminado en [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) y **reiniciar el servidor de desarrollo** para previsualizar el nuevo esquema de colores.
## Blanco Cebollino
![Light mode](../_images/1-light.jpeg)
![Dark mode](../_images/1-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0.03 211.86)',
secondary: 'oklch(0.40 0.03 211.86)',
background: 'oklch(0.99 0.0039 106.47)',
},
dark: {
primary: 'oklch(0.92 0.0015 106.47)',
secondary: 'oklch(0.79 0.0015 106.47)',
background: 'oklch(0.24 0.0039 106.47)',
},
```
## Azul Cuervo
![Light mode](../_images/2-light.jpeg)
![Dark mode](../_images/2-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.0172 280.05)',
secondary: 'oklch(0.40 0.0172 280.05)',
background: 'oklch(0.98 0.0172 280.05)',
},
dark: {
primary: 'oklch(0.92 0.0172 280.05)',
secondary: 'oklch(0.79 0.0172 280.05)',
background: 'oklch(0.24 0.0172 280.05)',
},
```
## Azul Tinta
![Light mode](../_images/4-light.jpeg)
![Dark mode](../_images/4-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.053 261.24)',
secondary: 'oklch(0.39 0.053 261.24)',
background: 'oklch(1 0 0)',
},
dark: {
primary: 'oklch(0.92 0 0)',
secondary: 'oklch(0.79 0 0)',
background: 'oklch(0.24 0.016 265.21)',
},
```
## Beige
![Light mode](../_images/3-light.jpeg)
![Dark mode](../_images/3-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0 0)',
secondary: 'oklch(0.41 0 0)',
background: 'oklch(0.95 0.0237 59.39)',
},
dark: {
primary: 'oklch(0.93 0.019 59.39)',
secondary: 'oklch(0.80 0.017 59.39)',
background: 'oklch(0.23 0 0)',
},
```

View file

@ -0,0 +1,85 @@
---
title: テーマカラースキーム
published: 2025-04-11
tags:
- ガイド
toc: false
lang: ja
abbrlink: theme-color-schemes
---
Retypesetは、[OKLCH](https://oklch.com/)カラースペースに基づいてテーマカラーを定義し、デフォルトでは印刷スタイルを模した白黒グレーの配色を採用しています。
個性的なニーズに応えるため、テーマ用にいくつかの配色スキームを作成しました。[src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) でデフォルトの配色を置き換え、**開発サーバーを再起動**して新しい配色をプレビューできます。
## 葱白色
![Light mode](../_images/1-light.jpeg)
![Dark mode](../_images/1-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0.03 211.86)',
secondary: 'oklch(0.40 0.03 211.86)',
background: 'oklch(0.99 0.0039 106.47)',
},
dark: {
primary: 'oklch(0.92 0.0015 106.47)',
secondary: 'oklch(0.79 0.0015 106.47)',
background: 'oklch(0.24 0.0039 106.47)',
},
```
## 烏青
![Light mode](../_images/2-light.jpeg)
![Dark mode](../_images/2-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.0172 280.05)',
secondary: 'oklch(0.40 0.0172 280.05)',
background: 'oklch(0.98 0.0172 280.05)',
},
dark: {
primary: 'oklch(0.92 0.0172 280.05)',
secondary: 'oklch(0.79 0.0172 280.05)',
background: 'oklch(0.24 0.0172 280.05)',
},
```
## 墨藍
![Light mode](../_images/4-light.jpeg)
![Dark mode](../_images/4-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.053 261.24)',
secondary: 'oklch(0.39 0.053 261.24)',
background: 'oklch(1 0 0)',
},
dark: {
primary: 'oklch(0.92 0 0)',
secondary: 'oklch(0.79 0 0)',
background: 'oklch(0.24 0.016 265.21)',
},
```
## 米色
![Light mode](../_images/3-light.jpeg)
![Dark mode](../_images/3-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0 0)',
secondary: 'oklch(0.41 0 0)',
background: 'oklch(0.95 0.0237 59.39)',
},
dark: {
primary: 'oklch(0.93 0.019 59.39)',
secondary: 'oklch(0.80 0.017 59.39)',
background: 'oklch(0.23 0 0)',
},
```

View file

@ -0,0 +1,85 @@
---
title: Цветовые Схемы Темы
published: 2025-04-11
tags:
- Руководство
toc: false
lang: ru
abbrlink: theme-color-schemes
---
Retypeset определяет цветовые схемы темы на основе цветового пространства [OKLCH](https://oklch.com/), с предустановленной схемой черного, белого и серого цветов, имитирующей печатный стиль.
Для удовлетворения потребностей в персонализации я создал несколько цветовых схем для темы. Вы можете заменить стандартную цветовую схему в [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) и **перезапустить сервер разработки**, чтобы просмотреть новую цветовую схему.
## Бледно-зелёный
![Light mode](../_images/1-light.jpeg)
![Dark mode](../_images/1-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0.03 211.86)',
secondary: 'oklch(0.40 0.03 211.86)',
background: 'oklch(0.99 0.0039 106.47)',
},
dark: {
primary: 'oklch(0.92 0.0015 106.47)',
secondary: 'oklch(0.79 0.0015 106.47)',
background: 'oklch(0.24 0.0039 106.47)',
},
```
## Воронёный
![Light mode](../_images/2-light.jpeg)
![Dark mode](../_images/2-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.0172 280.05)',
secondary: 'oklch(0.40 0.0172 280.05)',
background: 'oklch(0.98 0.0172 280.05)',
},
dark: {
primary: 'oklch(0.92 0.0172 280.05)',
secondary: 'oklch(0.79 0.0172 280.05)',
background: 'oklch(0.24 0.0172 280.05)',
},
```
## Чернильно-синий
![Light mode](../_images/4-light.jpeg)
![Dark mode](../_images/4-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.053 261.24)',
secondary: 'oklch(0.39 0.053 261.24)',
background: 'oklch(1 0 0)',
},
dark: {
primary: 'oklch(0.92 0 0)',
secondary: 'oklch(0.79 0 0)',
background: 'oklch(0.24 0.016 265.21)',
},
```
## Кремовый
![Light mode](../_images/3-light.jpeg)
![Dark mode](../_images/3-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0 0)',
secondary: 'oklch(0.41 0 0)',
background: 'oklch(0.95 0.0237 59.39)',
},
dark: {
primary: 'oklch(0.93 0.019 59.39)',
secondary: 'oklch(0.80 0.017 59.39)',
background: 'oklch(0.23 0 0)',
},
```

View file

@ -0,0 +1,85 @@
---
title: 主題配色指南
published: 2025-04-11
tags:
- 指南
toc: false
lang: zh-tw
abbrlink: theme-color-schemes
---
Retypeset 基於 [OKLCH](https://oklch.com/) 顏色空間來定義主題配色,預設為模擬印刷風格的黑白灰配色。
為滿足個性化需求,我為主題製作了一些配色方案。你可以在 [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) 中替換預設配色,並**重新啟動開發伺服器**以預覽新配色。
## 蔥白
![Light mode](../_images/1-light.jpeg)
![Dark mode](../_images/1-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0.03 211.86)',
secondary: 'oklch(0.40 0.03 211.86)',
background: 'oklch(0.99 0.0039 106.47)',
},
dark: {
primary: 'oklch(0.92 0.0015 106.47)',
secondary: 'oklch(0.79 0.0015 106.47)',
background: 'oklch(0.24 0.0039 106.47)',
},
```
## 鴉青
![Light mode](../_images/2-light.jpeg)
![Dark mode](../_images/2-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.0172 280.05)',
secondary: 'oklch(0.40 0.0172 280.05)',
background: 'oklch(0.98 0.0172 280.05)',
},
dark: {
primary: 'oklch(0.92 0.0172 280.05)',
secondary: 'oklch(0.79 0.0172 280.05)',
background: 'oklch(0.24 0.0172 280.05)',
},
```
## 墨藍
![Light mode](../_images/4-light.jpeg)
![Dark mode](../_images/4-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.053 261.24)',
secondary: 'oklch(0.39 0.053 261.24)',
background: 'oklch(1 0 0)',
},
dark: {
primary: 'oklch(0.92 0 0)',
secondary: 'oklch(0.79 0 0)',
background: 'oklch(0.24 0.016 265.21)',
},
```
## 米黃
![Light mode](../_images/3-light.jpeg)
![Dark mode](../_images/3-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0 0)',
secondary: 'oklch(0.41 0 0)',
background: 'oklch(0.95 0.0237 59.39)',
},
dark: {
primary: 'oklch(0.93 0.019 59.39)',
secondary: 'oklch(0.80 0.017 59.39)',
background: 'oklch(0.23 0 0)',
},
```

View file

@ -0,0 +1,85 @@
---
title: 主题配色指南
published: 2025-04-11
tags:
- 指南
toc: false
lang: zh
abbrlink: theme-color-schemes
---
Retypeset 基于 [OKLCH](https://oklch.com/) 颜色空间来定义主题配色,默认为模拟印刷风格的黑白灰配色。
为满足个性化需求,我为主题制作了一些配色方案。你可以在 [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) 中替换默认配色,并**重启开发服务器**以预览新配色。
## 葱白
![Light mode](../_images/1-light.jpeg)
![Dark mode](../_images/1-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0.03 211.86)',
secondary: 'oklch(0.40 0.03 211.86)',
background: 'oklch(0.99 0.0039 106.47)',
},
dark: {
primary: 'oklch(0.92 0.0015 106.47)',
secondary: 'oklch(0.79 0.0015 106.47)',
background: 'oklch(0.24 0.0039 106.47)',
},
```
## 鸦青
![Light mode](../_images/2-light.jpeg)
![Dark mode](../_images/2-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.0172 280.05)',
secondary: 'oklch(0.40 0.0172 280.05)',
background: 'oklch(0.98 0.0172 280.05)',
},
dark: {
primary: 'oklch(0.92 0.0172 280.05)',
secondary: 'oklch(0.79 0.0172 280.05)',
background: 'oklch(0.24 0.0172 280.05)',
},
```
## 墨蓝
![Light mode](../_images/4-light.jpeg)
![Dark mode](../_images/4-dark.jpeg)
```
light: {
primary: 'oklch(0.24 0.053 261.24)',
secondary: 'oklch(0.39 0.053 261.24)',
background: 'oklch(1 0 0)',
},
dark: {
primary: 'oklch(0.92 0 0)',
secondary: 'oklch(0.79 0 0)',
background: 'oklch(0.24 0.016 265.21)',
},
```
## 米黄
![Light mode](../_images/3-light.jpeg)
![Dark mode](../_images/3-dark.jpeg)
```
light: {
primary: 'oklch(0.25 0 0)',
secondary: 'oklch(0.41 0 0)',
background: 'oklch(0.95 0.0237 59.39)',
},
dark: {
primary: 'oklch(0.93 0.019 59.39)',
secondary: 'oklch(0.80 0.017 59.39)',
background: 'oklch(0.23 0 0)',
},
```

View file

@ -1,18 +1,20 @@
---
title: Theme Guide
published: 2025-01-26
updated: 2025-03-12
tags: ["Blog Theme","Guide"]
updated: 2025-04-13
tags:
- Blog Theme
- Guide
pin: 99
lang: en
abbrlink: theme-guide
---
Retypeset is a static blog theme based on the [Astro](https://astro.build/) framework. Inspired by [Typography](https://astro-theme-typography.vercel.app/), Retypeset establishes a new visual standard and reimagines the layout of all pages, creating a reading experience reminiscent of paper books, reviving the beauty of typography. Details in every sight, elegance in every space.
Retypeset is a static blog theme based on the [Astro](https://astro.build/) framework. This guide introduces how to modify theme configuration and create new articles, helping you quickly set up your personal blog.
## Theme Configuration
Below is the theme configuration guide for Retypeset. Customize your blog by modifying the configuration file [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts).
Customize your blog by modifying the configuration file [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts).
### Site Information
@ -32,7 +34,7 @@ site: {
url: 'https://retypeset.radishzz.cc'
// favicon url
// recommended formats: svg, png or ico
favicon: '/icon/favicon.svg' // or https://example.com/favicon.svg
favicon: '/icons/favicon.svg' // or https://example.com/favicon.svg
}
```
@ -56,10 +58,8 @@ color: {
// dark mode
dark: {
// primary color
// used for title, hover, etc
primary: 'oklch(92% 0.005 298)'
// secondary color
// used for post text
secondary: 'oklch(77% 0.005 298)'
// background color
background: 'oklch(22% 0.005 298)'
@ -73,19 +73,23 @@ color: {
global: {
// default language
// language of the site root path '/'
locale: 'zh' // zh, zh-tw, ja, en, es, ru
locale: 'zh' // de, en, es, fr, ja, ko, pl, pt, ru, zh, zh-tw
// more languages
// Generate multi-language paths such as '/es/' '/ru/'
// do not include the default language again, can be an empty array []
moreLocales: ['zh-tw', 'ja', 'en', 'es', 'ru'] // ['zh', 'zh-tw', 'ja', 'en', 'es', 'ru']
// generate multi-language paths such as '/en/' '/es/'
// not fill in the locale code above again, can be an empty array []
moreLocales: ['en', 'es', 'ja', 'ru', 'zh-tw'] // ['de', 'en', 'es', 'fr', 'ja', 'ko', 'pl', 'pt', 'ru', 'zh', 'zh-tw']
// font style
fontStyle: 'sans' // sans, serif
// date format for posts
dateFormat: 'YYYY-MM-DD' // YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// gap between title and subtitle
titleGap: 2 // 1, 2, 3
// YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// 2025-04-13, 04-13-2025, 13-04-2025, Apr 13 202513 Apr 2025
dateFormat: 'YYYY-MM-DD'
// enable table of contents for all posts by default
toc: true // true, false
// enable KaTeX for mathematical formulas rendering
katex: true // true, false
// reduce animations and transitions to improve performance
reduceMotion: false // true, false
}
```
@ -156,23 +160,23 @@ footer: {
links: [
{
name: 'RSS',
url: '/rss.xml', // rss.xml, atom.xml
url: '/atom.xml', // or /rss.xml
},
{
name: 'GitHub',
url: 'https://github.com/radishzzz/astro-theme-retypeset',
},
{
name: 'Twitter',
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,9 +186,8 @@ footer: {
preload: {
// link prefetch strategies
linkPrefetch: 'viewport' // hover, tap, viewport, load
// comment server url
commentURL: 'https://retypeset-comment.radishzz.cc'
// image hosting url
// optimize remote images in Markdown files to avoid cumulative layout shift
imageHostURL: 'https://image.radishzz.cc'
// custom google analytics js
// for users who route analytics javascript to a customized domain
@ -195,12 +198,103 @@ preload: {
}
```
## Additional Configuration
Besides the configuration file `src/config.ts`, some configuration options are located in other files.
### Syntax Highlighting
Code block syntax highlighting themes.
```ts
// astro.config.ts
shikiConfig: {
// Available themes: https://shiki.style/themes
// Background color follows the blog theme by default, not the syntax highlighting theme
themes: {
light: 'github-light' // Light theme
dark: 'github-dark' // Dark theme
}
}
```
### Article Excerpt
Character count for automatic article excerpts.
```ts
// src/utils/description.ts
const EXCERPT_LENGTHS: Record<ExcerptScene, {
cjk: number // Chinese, Japanese, Korean
other: number // Other languages
}> = {
list: { // Homepage post list
cjk: 120, // Auto-excerpts first 120 characters
other: 240, // Auto-excerpts first 240 characters
},
}
```
### Open Graph
[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
getImageOptions: (_path, page) => ({
logo: {
path: './public/icons/og-logo.png', // Required local path and PNG format
size: [250], // Logo width
},
font: {
title: { // Title
families: ['Noto Sans SC'], // Font
weight: 'Bold', // Weight
color: [34, 33, 36], // Color
lineHeight: 1.5, // Line height
},
},
fonts: [ // Font paths (local or remote)
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Bold.otf',
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Regular.otf',
],
bgGradient: [[242, 241, 245]], // Background color
// More configurations: https://github.com/delucis/astro-og-canvas/tree/latest/packages/astro-og-canvas
})
```
### RSS Feed
[RSS feed page](https://retypeset.radishzz.cc/en/rss.xml) styles.
```html
<!-- public/feeds/xxx-style.xsl -->
<style type="text/css">
body{color:oklch(25% 0.005 298)} /* Font color */
.bg-white{background-color:oklch(0.96 0.005 298)!important} /* Background color */
.text-gray{color:oklch(0.25 0.005 298 / 75%)!important} /* Secondary font color */
</style>
```
## Creating a New Post
Create a new file with `.md` or `.mdx` extension in the `src/content/posts/` directory, and add Front Matter metadata at the top of the file.
Run `pnpm new-post <filename>` to create a new post, which can then be edited in the `src/content/posts/` directory.
```bash
pnpm new-post -> src/content/posts/new-post.md
pnpm new-post first-post -> src/content/posts/first-post.md
pnpm new-post 2025/03/first-post -> src/content/posts/2025/03/first-post.md
pnpm new-post first-post.mdx -> src/content/posts/first-post.mdx
```
### Front Matter
Only `title` and `published` are required fields, all other configurations can be safely omitted.
```markdown
---
# Required
@ -208,15 +302,17 @@ title: Theme Guide
published: 2025-01-26
# Optional
description: The first 240 characters of the article will be automatically selected as the description.
description: The first 240 characters of the article will be automatically selected as the excerpt.
updated: 2025-03-26
tags: ["Blog Theme", "Guide"]
tags:
- Blog Theme
- Guide
# Advanced, optional
# Advanced, Optional
draft: true/false
pin: 1-99
pin: 0-99
toc: true/false
lang: en/es/ru/zh/zh-tw/ja
lang: de/en/es/fr/ja/ko/pl/pt/ru/zh/zh-tw
abbrlink: theme-guide
---
```
@ -233,7 +329,7 @@ Pins the article to the top. The higher the number, the higher the priority of t
#### toc
Generate table of contents. Default is true.
Generate table of contents. Shows h2 to h4 headings. Determined by the global configuration `global.toc` by default, but can be overridden individually in each article.
#### lang
@ -245,20 +341,20 @@ Specifies the article language. Only one language can be specified. If not speci
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/apple.md -> example.com/es/posts/apple/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/apple.md -> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink
Customizes the article URL.
Customizes the article URL. Can only contain lowercase letters, numbers, and hyphens `-`.
```md
# src/config.ts
@ -276,7 +372,3 @@ src/content/posts/apple.md -> example.com/es/posts/banana/
src/content/posts/guide/apple.md -> example.com/es/posts/banana/
src/content/posts/2025/03/apple.md -> example.com/es/posts/banana/
```
### Automated Features
Automatically calculates article reading time. Automatically generates Open Graph images for each article. Articles with the same abbrlink will automatically share Waline comments, regardless of the lang configuration.

View file

@ -1,18 +1,20 @@
---
title: Guía del Tema
published: 2025-01-26
updated: 2025-03-12
tags: ["Tema de Blog","Guía"]
updated: 2025-04-13
tags:
- Tema de Blog
- Guía
pin: 99
lang: es
abbrlink: theme-guide
---
Retypeset es un tema de blog estático basado en el framework [Astro](https://astro.build/). Inspirado por [Typography](https://astro-theme-typography.vercel.app/), Retypeset establece un nuevo estándar visual y reimagina el diseño de todas las páginas, creando una experiencia de lectura similar a la de los libros impresos, reviviendo la belleza de la tipografía. Detalles en cada mirada, elegancia en cada espacio.
Retypeset es un tema de blog estático basado en el framework [Astro](https://astro.build/). Esta guía presenta cómo modificar la configuración del tema y crear nuevos artículos, ayudándote a configurar rápidamente tu blog personal.
## Configuración del Tema
A continuación se presenta la guía de configuración del tema Retypeset. Personaliza tu blog modificando el archivo de configuración [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts).
Personaliza tu blog mediante la modificación del archivo de configuración [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts).
### Información del Sitio
@ -24,7 +26,7 @@ site: {
subtitle: 'Revive the beauty of typography'
// descripción del sitio
description: 'Retypeset is a static blog theme...'
// usar título/subtítulo/descripción en varios idiomas desde src/i18n/ui.ts en lugar de los estáticos anteriores
// usar título/subtítulo/descripción en varios idiomas desde src/i18n/ui.ts en lugar de los estáticos de arriba
i18nTitle: true // true, false
// nombre del autor
author: 'radishzz'
@ -32,7 +34,7 @@ site: {
url: 'https://retypeset.radishzz.cc'
// url del favicon
// formatos recomendados: svg, png o ico
favicon: '/icon/favicon.svg' // o https://example.com/favicon.svg
favicon: '/icons/favicon.svg' // o https://example.com/favicon.svg
}
```
@ -56,10 +58,8 @@ color: {
// modo oscuro
dark: {
// color primario
// usado para títulos, hover, etc
primary: 'oklch(92% 0.005 298)'
// color secundario
// usado para texto de publicaciones
secondary: 'oklch(77% 0.005 298)'
// color de fondo
background: 'oklch(22% 0.005 298)'
@ -73,19 +73,23 @@ color: {
global: {
// idioma predeterminado
// idioma de la ruta raíz del sitio '/'
locale: 'zh' // zh, zh-tw, ja, en, es, ru
locale: 'zh' // de, en, es, fr, ja, ko, pl, pt, ru, zh, zh-tw
// más idiomas
// Genera rutas multilingües como '/es/' '/ru/'
// no incluir el idioma predeterminado nuevamente, puede ser un array vacío []
moreLocales: ['zh-tw', 'ja', 'en', 'es', 'ru'] // ['zh', 'zh-tw', 'ja', 'en', 'es', 'ru']
// genera rutas multilingües como '/en/' '/es/'
// no incluir el código de idioma anterior nuevamente, puede ser un array vacío []
moreLocales: ['en', 'es', 'ja', 'ru', 'zh-tw'] // ['de', 'en', 'es', 'fr', 'ja', 'ko', 'pl', 'pt', 'ru', 'zh', 'zh-tw']
// estilo de fuente
fontStyle: 'sans' // sans, serif
// formato de fecha para publicaciones
dateFormat: 'YYYY-MM-DD' // YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// espacio entre título y subtítulo
titleGap: 2 // 1, 2, 3
// YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// 2025-04-13, 04-13-2025, 13-04-2025, Apr 13 202513 Apr 2025
dateFormat: 'YYYY-MM-DD'
// habilitar tabla de contenidos para todos los artículos por defecto
toc: true // true, false
// habilitar KaTeX para renderizar fórmulas matemáticas
katex: true // true, false
// reducir animaciones y transiciones para mejorar el rendimiento
reduceMotion: false // true, false
}
```
@ -156,23 +160,23 @@ footer: {
links: [
{
name: 'RSS',
url: '/rss.xml', // rss.xml, atom.xml
url: '/atom.xml', // o /rss.xml
},
{
name: 'GitHub',
url: 'https://github.com/radishzzz/astro-theme-retypeset',
},
{
name: 'Twitter',
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,9 +186,8 @@ 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
// optimizar imágenes remotas en archivos Markdown para evitar cambios de diseño acumulativos
imageHostURL: 'https://image.radishzz.cc'
// js personalizado de google analytics
// para usuarios que redirigen javascript de analytics a un dominio personalizado
@ -195,12 +198,103 @@ preload: {
}
```
## Configuración Adicional
Además del archivo de configuración `src/config.ts`, algunas opciones de configuración se encuentran en otros archivos.
### Resaltado de Sintaxis
Temas de resaltado de sintaxis para bloques de código.
```ts
// astro.config.ts
shikiConfig: {
// Temas disponibles: https://shiki.style/themes
// El color de fondo sigue el tema del blog por defecto, no el tema de resaltado de sintaxis
themes: {
light: 'github-light' // Tema claro
dark: 'github-dark' // Tema oscuro
}
}
```
### Extracto de Artículo
Cantidad de caracteres para extractos automáticos de artículos.
```ts
// src/utils/description.ts
const EXCERPT_LENGTHS: Record<ExcerptScene, {
cjk: number // Chino, Japonés, Coreano
other: number // Otros idiomas
}> = {
list: { // Lista de publicaciones en página principal
cjk: 120, // Extrae automáticamente los primeros 120 caracteres
other: 240, // Extrae automáticamente los primeros 240 caracteres
},
}
```
### 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
getImageOptions: (_path, page) => ({
logo: {
path: './public/icons/og-logo.png', // Ruta local requerida y formato PNG
size: [250], // Ancho del logo
},
font: {
title: { // Título
families: ['Noto Sans SC'], // Fuente
weight: 'Bold', // Peso
color: [34, 33, 36], // Color
lineHeight: 1.5, // Altura de línea
},
},
fonts: [ // Rutas de fuentes (locales o remotas)
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Bold.otf',
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Regular.otf',
],
bgGradient: [[242, 241, 245]], // Color de fondo
// Más configuraciones: https://github.com/delucis/astro-og-canvas/tree/latest/packages/astro-og-canvas
})
```
### Canal RSS
Estilos de [página del feed RSS](https://retypeset.radishzz.cc/es/rss.xml).
```html
<!-- public/feeds/xxx-style.xsl -->
<style type="text/css">
body{color:oklch(25% 0.005 298)} /* Color de fuente */
.bg-white{background-color:oklch(0.96 0.005 298)!important} /* Color de fondo */
.text-gray{color:oklch(0.25 0.005 298 / 75%)!important} /* Color de fuente secundario */
</style>
```
## Creación de un Nuevo Artículo
Crea un nuevo archivo con extensión `.md` o `.mdx` en el directorio `src/content/posts/`, y añade los metadatos Front Matter en la parte superior del archivo.
Ejecuta `pnpm new-post <filename>` para crear un nuevo artículo, que luego puede editarse en el directorio `src/content/posts/`.
```bash
pnpm new-post -> src/content/posts/new-post.md
pnpm new-post first-post -> src/content/posts/first-post.md
pnpm new-post 2025/03/first-post -> src/content/posts/2025/03/first-post.md
pnpm new-post first-post.mdx -> src/content/posts/first-post.mdx
```
### Front Matter
Solo los campos `title` y `published` son obligatorios, todas las demás configuraciones pueden omitirse de forma segura.
```markdown
---
# Obligatorio
@ -208,15 +302,17 @@ title: Guía del Tema
published: 2025-01-26
# Opcional
description: Los primeros 240 caracteres del artículo se seleccionarán automáticamente como descripción.
description: Los primeros 240 caracteres del artículo se seleccionarán automáticamente como extracto.
updated: 2025-03-26
tags: ["Tema de Blog", "Guía"]
tags:
- Tema de Blog
- Guía
# Avanzado, opcional
# Avanzado, Opcional
draft: true/false
pin: 1-99
pin: 0-99
toc: true/false
lang: en/es/ru/zh/zh-tw/ja
lang: de/en/es/fr/ja/ko/pl/pt/ru/zh/zh-tw
abbrlink: theme-guide
---
```
@ -233,7 +329,7 @@ Fija el artículo en la parte superior. Cuanto mayor sea el número, mayor será
#### toc
¿Generar índice? Valor predeterminado: true.
Genera tabla de contenidos. Muestra encabezados de h2 a h4. Determinado por la configuración global `global.toc` por defecto, pero puede ser modificada individualmente en cada artículo.
#### lang
@ -245,20 +341,20 @@ Especifica el idioma del artículo. Solo se puede especificar un idioma. Si no s
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/apple.md -> example.com/es/posts/apple/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/apple.md -> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink
Personaliza la URL del artículo.
Personaliza la URL del artículo. Solo puede contener letras minúsculas, números y guiones `-`.
```md
# src/config.ts
@ -276,7 +372,3 @@ src/content/posts/apple.md -> example.com/es/posts/banana/
src/content/posts/guide/apple.md -> example.com/es/posts/banana/
src/content/posts/2025/03/apple.md -> example.com/es/posts/banana/
```
### Funciones Automatizadas
Calcula automáticamente el tiempo de lectura del artículo. Genera automáticamente imágenes Open Graph para cada artículo. Los artículos con el mismo abbrlink compartirán automáticamente comentarios de Waline, independientemente de la configuración de lang.

View file

@ -1,18 +1,20 @@
---
title: テーマ使用ガイド
published: 2025-01-26
updated: 2025-03-12
tags: ["ブログテーマ","ガイド"]
updated: 2025-04-13
tags:
- ブログテーマ
- ガイド
pin: 99
lang: ja
abbrlink: theme-guide
---
Retypesetは、日本語では「再組版」と呼ばれる、[Astro](https://astro.build/) フレームワークをベースにした静的ブログテーマです。[活版印字](https://astro-theme-typography.vercel.app/) からデザインのインスピレーションを得て、新しい視覚的な規範を確立し、すべてのページのレイアウトを再構成することで、紙の書籍のような読書体験を提供し、版面の美しさを蘇らせます。見るものすべてが細部にこだわり、限られたスペースの中に優雅さを表現しています。
Retypesetは、日本語では「再組版」と呼ばれる、[Astro](https://astro.build/) フレームワークをベースにした静的ブログテーマです。本ガイドではテーマの設定変更方法と新しい記事の作成方法を紹介し、個人ブログを素早く構築できるよう支援します。
## テーマ設定
以下はRetypesetのテーマ設定ガイドです。設定ファイル [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) を修正してブログをカスタマイズできます。
設定ファイル [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) を変更してあなたのブログをカスタマイズできます。
### サイト情報
@ -32,7 +34,7 @@ site: {
url: 'https://retypeset.radishzz.cc'
// ファビコンURL
// 推奨フォーマット: svg, png, ico
favicon: '/icon/favicon.svg' // または https://example.com/favicon.svg
favicon: '/icons/favicon.svg' // または https://example.com/favicon.svg
}
```
@ -56,10 +58,8 @@ color: {
// ダークモード
dark: {
// プライマリカラー
// サイトタイトル、ホバー効果などに使用
primary: 'oklch(92% 0.005 298)'
// セカンダリカラー
// 通常テキストに使用
secondary: 'oklch(77% 0.005 298)'
// 背景色
background: 'oklch(22% 0.005 298)'
@ -73,23 +73,27 @@ color: {
global: {
// デフォルト言語
// サイトのルートパス '/' の言語
locale: 'zh' // zh, zh-tw, ja, en, es, ru
locale: 'zh' // de, en, es, fr, ja, ko, pl, pt, ru, zh, zh-tw
// その他の言語
// '/ja/' '/en/' などの多言語パスを生成
// '/en/' '/es/' などの多言語パスを生成
// デフォルト言語を重複して入力しないでください、空の配列 [] も可能です
moreLocales: ['zh-tw', 'ja', 'en', 'es', 'ru'] // ['zh', 'zh-tw', 'ja', 'en', 'es', 'ru']
moreLocales: ['en', 'es', 'ja', 'ru', 'zh-tw'] // ['de', 'en', 'es', 'fr', 'ja', 'ko', 'pl', 'pt', 'ru', 'zh', 'zh-tw']
// フォントスタイル
fontStyle: 'sans' // sans, serif
// 記事の日付フォーマット
dateFormat: 'YYYY-MM-DD' // YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// タイトルとサブタイトルの間隔
titleGap: 2 // 1, 2, 3
// YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// 2025-04-13, 04-13-2025, 13-04-2025, Apr 13 202513 Apr 2025
dateFormat: 'YYYY-MM-DD'
// デフォルトですべての記事に目次を表示
toc: true // true, false
// 数式表示のためのKaTeXを有効化
katex: true // true, false
// アニメーションと遷移効果を減らしてパフォーマンスを向上させる
reduceMotion: false // true, false
}
```
### コメントサービス
### コメントシステム
```ts
comment: {
@ -156,23 +160,23 @@ footer: {
links: [
{
name: 'RSS',
url: '/rss.xml', // rss.xml, atom.xml
url: '/atom.xml', // または /rss.xml
},
{
name: 'GitHub',
url: 'https://github.com/radishzzz/astro-theme-retypeset',
},
{
name: 'Twitter',
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,9 +186,8 @@ footer: {
preload: {
// リンクプリフェッチ戦略
linkPrefetch: 'viewport' // hover, tap, viewport, load
// コメントサーバー URL
commentURL: 'https://retypeset-comment.radishzz.cc'
// 画像ホスティング URL
// Markdownファイル内のリモート画像を最適化してレイアウトシフトを防止
imageHostURL: 'https://image.radishzz.cc'
// カスタム Google Analytics JS
// アナリティクス JavaScript をカスタムドメインにルーティングするユーザー向け
@ -195,12 +198,103 @@ preload: {
}
```
## その他の設定
設定ファイル `src/config.ts` 以外にも、一部の設定は他のファイルにあります。
### シンタックスハイライト
コードブロックのシンタックスハイライトテーマ。
```ts
// astro.config.ts
shikiConfig: {
// 利用可能なテーマ: https://shiki.style/themes
// 背景色はデフォルトでシンタックスハイライトテーマではなく、ブログテーマに従います
themes: {
light: 'github-light' // ライトテーマ
dark: 'github-dark' // ダークテーマ
}
}
```
### 記事の抜粋
記事の自動抜粋の文字数。
```ts
// src/utils/description.ts
const EXCERPT_LENGTHS: Record<ExcerptScene, {
cjk: number // 中国語、日本語、韓国語
other: number // その他の言語
}> = {
list: { // ホームページ記事リスト
cjk: 120, // 先頭から120文字を自動抜粋
other: 240, // 先頭から240文字を自動抜粋
},
}
```
### 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
getImageOptions: (_path, page) => ({
logo: {
path: './public/icons/og-logo.png', // ローカルパスのPNG形式が必要
size: [250], // ロゴの幅
},
font: {
title: { // タイトル
families: ['Noto Sans SC'], // フォント
weight: 'Bold', // 太さ
color: [34, 33, 36], // 色
lineHeight: 1.5, // 行の高さ
},
},
fonts: [ // フォントパス(ローカルまたはリモート)
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Bold.otf',
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Regular.otf',
],
bgGradient: [[242, 241, 245]], // 背景色
// その他の設定: https://github.com/delucis/astro-og-canvas/tree/latest/packages/astro-og-canvas
})
```
### RSSフィード
[RSSフィードページ](https://retypeset.radishzz.cc/ja/rss.xml)スタイル。
```html
<!-- public/feeds/xxx-style.xsl -->
<style type="text/css">
body{color:oklch(25% 0.005 298)} /* フォントカラー */
.bg-white{background-color:oklch(0.96 0.005 298)!important} /* 背景色 */
.text-gray{color:oklch(0.25 0.005 298 / 75%)!important} /* セカンダリフォントカラー */
</style>
```
## 新しい記事の作成
`src/content/posts/` ディレクトリに `.md` または `.mdx` 拡張子を持つ新しいファイルを作成し、ファイルの先頭に Front Matter メタデータを追加します。
`pnpm new-post <filename>` を実行して新しい記事を作成し、`src/content/posts/` ディレクトリで編集できます。
```bash
pnpm new-post -> src/content/posts/new-post.md
pnpm new-post first-post -> src/content/posts/first-post.md
pnpm new-post 2025/03/first-post -> src/content/posts/2025/03/first-post.md
pnpm new-post first-post.mdx -> src/content/posts/first-post.mdx
```
### Front Matter
`title``published` のみが必須フィールドで、他のすべての設定は安全に省略できます。
```markdown
---
# 必須
@ -208,20 +302,22 @@ title: テーマ使用ガイド
published: 2025-01-26
# 任意
description: 記事の最初の120文字が自動的に説明として選択されます。
description: 記事の最初の120文字が自動的に要約として選択されます。
updated: 2025-03-26
tags: ["ブログテーマ", "ガイド"]
tags:
- ブログテーマ
- ガイド
# 高度な設定(任意)
draft: true/false
pin: 1-99
pin: 0-99
toc: true/false
lang: zh/zh-tw/ja/en/es/ru
lang: de/en/es/fr/ja/ko/pl/pt/ru/zh/zh-tw
abbrlink: theme-guide
---
```
### 高度な設定の説明
### 高度な設定
#### draft
@ -233,7 +329,7 @@ abbrlink: theme-guide
#### toc
目次を自動生成するかどうか。デフォルトは true
目次を生成するかどうか。h2からh4までの見出しを表示します。デフォルトではグローバル設定項目 `global.toc` によって決定されますが、記事ごとに個別に設定して上書きすることもできます
#### lang
@ -245,20 +341,20 @@ abbrlink: theme-guide
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/apple.md -> example.com/es/posts/apple/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/apple.md -> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink
記事のURLをカスタマイズします。
記事のURLをカスタマイズします。小文字、数字、ハイフン `-` のみ使用できます。
```md
# src/config.ts
@ -276,7 +372,3 @@ src/content/posts/apple.md -> example.com/es/posts/banana/
src/content/posts/guide/apple.md -> example.com/es/posts/banana/
src/content/posts/2025/03/apple.md -> example.com/es/posts/banana/
```
### 自動化機能の説明
記事の読書時間を自動的に計算します。各記事のOpen Graph画像を自動的に生成します。同じabbrlinkを持つ記事は、lang設定に関係なく、Walineコメントを自動的に共有します。

View file

@ -1,18 +1,20 @@
---
title: Руководство по теме
published: 2025-01-26
updated: 2025-03-12
tags: ["Тема блога","Руководство"]
updated: 2025-04-13
tags:
- Тема блога
- Руководство
pin: 99
lang: ru
abbrlink: theme-guide
---
Retypeset — это статическая тема блога, основанная на фреймворке [Astro](https://astro.build/). Вдохновленная [Typography](https://astro-theme-typography.vercel.app/), Retypeset устанавливает новый визуальный стандарт и переосмысливает компоновку всех страниц, создавая опыт чтения, напоминающий печатные книги, возрождая красоту типографики. Детали в каждом взгляде, элегантность в каждом пространстве.
Retypeset — это статическая тема блога, основанная на фреймворке [Astro](https://astro.build/). Данное руководство знакомит с тем, как изменять настройки темы и создавать новые статьи, помогая вам быстро настроить личный блог.
## Конфигурация темы
Ниже приведено руководство по конфигурации темы Retypeset. Настройте свой блог, изменяя конфигурационный файл [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts).
Настройте свой блог путем изменения конфигурационного файла [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts).
### Информация о сайте
@ -32,7 +34,7 @@ site: {
url: 'https://retypeset.radishzz.cc'
// url фавикона
// рекомендуемые форматы: svg, png или ico
favicon: '/icon/favicon.svg' // или https://example.com/favicon.svg
favicon: '/icons/favicon.svg' // или https://example.com/favicon.svg
}
```
@ -56,10 +58,8 @@ color: {
// темный режим
dark: {
// основной цвет
// используется для заголовков, эффекта наведения и т.д.
primary: 'oklch(92% 0.005 298)'
// вторичный цвет
// используется для текста постов
secondary: 'oklch(77% 0.005 298)'
// цвет фона
background: 'oklch(22% 0.005 298)'
@ -73,19 +73,23 @@ color: {
global: {
// язык по умолчанию
// язык корневого пути сайта '/'
locale: 'zh' // zh, zh-tw, ja, en, es, ru
locale: 'zh' // de, en, es, fr, ja, ko, pl, pt, ru, zh, zh-tw
// дополнительные языки
// Создает многоязычные пути, такие как '/es/' '/ru/'
// не указывайте повторно язык по умолчанию, можно оставить пустым массивом []
moreLocales: ['zh-tw', 'ja', 'en', 'es', 'ru'] // ['zh', 'zh-tw', 'ja', 'en', 'es', 'ru']
// создает многоязычные пути, такие как '/en/' '/es/'
// не указывайте код языка, указанный выше, можно оставить пустым массивом []
moreLocales: ['en', 'es', 'ja', 'ru', 'zh-tw'] // ['de', 'en', 'es', 'fr', 'ja', 'ko', 'pl', 'pt', 'ru', 'zh', 'zh-tw']
// стиль шрифта
fontStyle: 'sans' // sans, serif
// формат даты для постов
dateFormat: 'YYYY-MM-DD' // YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// промежуток между заголовком и подзаголовком
titleGap: 2 // 1, 2, 3
// YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// 2025-04-13, 04-13-2025, 13-04-2025, Apr 13 202513 Apr 2025
dateFormat: 'YYYY-MM-DD'
// включить оглавление для всех статей по умолчанию
toc: true // true, false
// включить KaTeX для отображения математических формул
katex: true // true, false
// уменьшить анимации и переходы для повышения производительности
reduceMotion: false // true, false
}
```
@ -156,23 +160,23 @@ footer: {
links: [
{
name: 'RSS',
url: '/rss.xml', // rss.xml, atom.xml
url: '/atom.xml', // или /rss.xml
},
{
name: 'GitHub',
url: 'https://github.com/radishzzz/astro-theme-retypeset',
},
{
name: 'Twitter',
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,9 +186,8 @@ footer: {
preload: {
// стратегии предзагрузки ссылок
linkPrefetch: 'viewport' // hover, tap, viewport, load
// URL сервера комментариев
commentURL: 'https://retypeset-comment.radishzz.cc'
// URL хостинга изображений
// оптимизировать удаленные изображения в файлах Markdown для избежания накопления сдвига макета
imageHostURL: 'https://image.radishzz.cc'
// пользовательский скрипт Google Analytics
// для пользователей, которые направляют JavaScript аналитики на собственный домен
@ -194,49 +197,143 @@ preload: {
customUmamiAnalyticsJS: 'https://js.radishzz.cc/jquery.min.js'
}
```
## Создание Новой Статьи
Создайте новый файл с расширением `.md` или `.mdx` в директории `src/content/posts/` и добавьте метаданные Front Matter в верхней части файла.
## Дополнительная конфигурация
Кроме файла конфигурации `src/config.ts`, некоторые параметры находятся в других файлах.
### Подсветка синтаксиса
Темы подсветки синтаксиса для блоков кода.
```ts
// astro.config.ts
shikiConfig: {
// Доступные темы: https://shiki.style/themes
// Цвет фона по умолчанию следует теме блога, а не теме подсветки синтаксиса
themes: {
light: 'github-light' // Светлая тема
dark: 'github-dark' // Темная тема
}
}
```
### Отрывок статьи
Количество символов для автоматических отрывков статей.
```ts
// src/utils/description.ts
const EXCERPT_LENGTHS: Record<ExcerptScene, {
cjk: number // Китайский, Японский, Корейский
other: number // Другие языки
}> = {
list: { // Список записей на главной странице
cjk: 120, // Автоматически берет первые 120 символов
other: 240, // Автоматически берет первые 240 символов
},
}
```
### 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
getImageOptions: (_path, page) => ({
logo: {
path: './public/icons/og-logo.png', // Требуется локальный путь и формат PNG
size: [250], // Ширина логотипа
},
font: {
title: { // Заголовок
families: ['Noto Sans SC'], // Шрифт
weight: 'Bold', // Вес
color: [34, 33, 36], // Цвет
lineHeight: 1.5, // Высота строки
},
},
fonts: [ // Пути к шрифтам (локальные или удаленные)
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Bold.otf',
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Regular.otf',
],
bgGradient: [[242, 241, 245]], // Цвет фона
// Дополнительные настройки: https://github.com/delucis/astro-og-canvas/tree/latest/packages/astro-og-canvas
})
```
### RSS-лента
Стили [страницы RSS-ленты](https://retypeset.radishzz.cc/ru/rss.xml).
```html
<!-- public/feeds/xxx-style.xsl -->
<style type="text/css">
body{color:oklch(25% 0.005 298)} /* Цвет шрифта */
.bg-white{background-color:oklch(0.96 0.005 298)!important} /* Цвет фона */
.text-gray{color:oklch(0.25 0.005 298 / 75%)!important} /* Вторичный цвет шрифта */
</style>
```
## Создание новой статьи
Выполните команду `pnpm new-post <filename>` для создания новой статьи, которую затем можно редактировать в директории `src/content/posts/`.
```bash
pnpm new-post -> src/content/posts/new-post.md
pnpm new-post first-post -> src/content/posts/first-post.md
pnpm new-post 2025/03/first-post -> src/content/posts/2025/03/first-post.md
pnpm new-post first-post.mdx -> src/content/posts/first-post.mdx
```
### Front Matter
Только поля `title` и `published` являются обязательными, все остальные конфигурации можно безопасно опустить.
```markdown
---
# Обязательно
# Обязательные
title: Руководство по теме
published: 2025-01-26
# Опционально
description: Первые 240 символов статьи будут автоматически выбраны в качестве описания.
# Опциональные
description: Первые 240 символов статьи будут автоматически выбраны в качестве отрывка.
updated: 2025-03-26
tags: ["Тема блога", "Руководство"]
tags:
- Тема блога
- Руководство
# Расширенные настройки, опционально
# Расширенные, опциональные
draft: true/false
pin: 1-99
pin: 0-99
toc: true/false
lang: en/es/ru/zh/zh-tw/ja
lang: de/en/es/fr/ja/ko/pl/pt/ru/zh/zh-tw
abbrlink: theme-guide
---
```
### Расширенная Конфигурация
### Расширенные настройки
#### draft
Помечает статью как черновик. Если установлено значение true, статья не может быть опубликована и доступна только для предварительного просмотра при локальной разработке. По умолчанию - false.
Отметить статью как черновик. Когда установлено значение true, статью нельзя опубликовать, и она доступна только для локального предварительного просмотра. По умолчанию — false.
#### pin
Закрепляет статью вверху. Чем выше число, тем выше приоритет закрепленной статьи. По умолчанию - 0, что означает отсутствие закрепления.
Закрепить статью вверху. Чем выше число, тем выше приоритет закрепленной статьи. По умолчанию 0, что означает отсутствие закрепления.
#### toc
Генерировать оглавление. По умолчанию: true.
Генерировать оглавление. Показывает заголовки от h2 до h4. По умолчанию определяется глобальным параметром `global.toc`, но может быть изменен индивидуально в каждой статье.
#### lang
Указывает язык статьи. Можно указать только один язык. Если не указано, статья будет отображаться во всех языковых путях по умолчанию.
Указывает язык статьи. Можно указать только один язык. Если не указано, статья будет отображаться по умолчанию во всех языковых путях.
```md
# src/config.ts
@ -244,20 +341,20 @@ abbrlink: theme-guide
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/apple.md -> example.com/es/posts/apple/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/apple.md -> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink
Настраивает URL статьи.
Настраивает URL статьи. Может содержать только строчные буквы, цифры и дефисы `-`.
```md
# src/config.ts
@ -275,7 +372,3 @@ src/content/posts/apple.md -> example.com/es/posts/banana/
src/content/posts/guide/apple.md -> example.com/es/posts/banana/
src/content/posts/2025/03/apple.md -> example.com/es/posts/banana/
```
### Автоматические Функции
Автоматически рассчитывает время чтения статьи. Автоматически генерирует изображения Open Graph для каждой статьи. Статьи с одинаковым abbrlink будут автоматически совместно использовать комментарии Waline, независимо от настройки lang.

View file

@ -1,18 +1,20 @@
---
title: 主題上手指南
published: 2025-01-26
updated: 2025-03-12
tags: ["部落格主題","指南"]
updated: 2025-04-13
tags:
- 部落格主題
- 指南
pin: 99
lang: zh-tw
abbrlink: theme-guide
---
Retypeset 是一款基於 [Astro](https://astro.build/) 框架的靜態部落格主題,中文名為重新編排。本主題以 [活版印字](https://astro-theme-typography.vercel.app/) 為設計靈感,通過建立全新的視覺規範,對所有頁面進行重新編排,打造紙質書頁般的閱讀體驗,再現版式之美。所見皆為細節,方寸盡顯優雅
Retypeset 是一款基於 [Astro](https://astro.build/) 框架的靜態部落格主題,中文名為重新編排。本文為 Retypeset 主題上手指南,主要介紹如何修改主題配置與創建新文章,來幫助你快速搭建個人部落格
## 主題配置
以下為 Retypeset 的主題配置介紹。通過修改配置文件 [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) 來自定義你的部落格。
通過修改配置文件 [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) 來自定義你的部落格。
### 站點信息
@ -22,9 +24,9 @@ site: {
title: 'Retypeset'
// 站點副標題
subtitle: 'Revive the beauty of typography'
// 站點介紹
// 站點描述
description: 'Retypeset is a static blog theme...'
// 使用 src/i18n/ui.ts 中的多語言標題/副標題/站點描述,替換以上靜態配置
// 使用 src/i18n/ui.ts 中的多語言標題/副標題/站點描述,代替上方靜態配置
i18nTitle: true // true, false
// 作者名稱
author: 'radishzz'
@ -32,7 +34,7 @@ site: {
url: 'https://retypeset.radishzz.cc'
// 站點圖標
// 推薦格式: svg, png, ico
favicon: '/icon/favicon.svg' // 或 https://example.com/favicon.svg
favicon: '/icons/favicon.svg' // 或 https://example.com/favicon.svg
}
```
@ -56,10 +58,8 @@ color: {
// 暗色模式
dark: {
// 高亮顏色
// 用於站點標題、滑鼠懸停效果等
primary: 'oklch(92% 0.005 298)'
// 次要顏色
// 用於普通文本
secondary: 'oklch(77% 0.005 298)'
// 背景色
background: 'oklch(22% 0.005 298)'
@ -73,23 +73,27 @@ color: {
global: {
// 默認語言
// 站點根路徑 '/' 的語言
locale: 'zh' // zh, zh-tw, ja, en, es, ru
locale: 'zh' // de, en, es, fr, ja, ko, pl, pt, ru, zh, zh-tw
// 更多語言
// 生成 '/ja/' '/en/' 等多語言路徑
// 生成 '/en/' '/es/' 等多語言路徑
// 不要重複填寫默認語言,可以為空 []
moreLocales: ['zh-tw', 'ja', 'en', 'es', 'ru'] // ['zh', 'zh-tw', 'ja', 'en', 'es', 'ru']
moreLocales: ['en', 'es', 'ja', 'ru', 'zh-tw'] // ['de', 'en', 'es', 'fr', 'ja', 'ko', 'pl', 'pt', 'ru', 'zh', 'zh-tw']
// 字體樣式
fontStyle: 'sans' // sans, serif
// 文章日期格式
dateFormat: 'YYYY-MM-DD' // YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// 標題與副標題之間的距離
titleGap: 2 // 1, 2, 3
// YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// 2025-04-13, 04-13-2025, 13-04-2025, Apr 13 202513 Apr 2025
dateFormat: 'YYYY-MM-DD'
// 預設為所有文章開啟目錄
toc: true // true, false
// 啟用 KaTeX 數學公式渲染
katex: true // true, false
// 減少動畫和過渡效果以提高性能
reduceMotion: false // true, false
}
```
### 評論服務
### 評論系統
```ts
comment: {
@ -156,23 +160,23 @@ footer: {
links: [
{
name: 'RSS',
url: '/rss.xml', // rss.xml, atom.xml
url: '/atom.xml', // 或 /rss.xml
},
{
name: 'GitHub',
url: 'https://github.com/radishzzz/astro-theme-retypeset',
},
{
name: 'Twitter',
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,9 +186,8 @@ footer: {
preload: {
// 鏈接預加載策略
linkPrefetch: 'viewport' // hover, tap, viewport, load
// 評論服務器地址
commentURL: 'https://retypeset-comment.radishzz.cc'
// 圖床地址
// 優化 Markdown 文件中的遠程圖片以避免佈局抖動
imageHostURL: 'https://image.radishzz.cc'
// 定制 google analytics js
// 適用於路由 google analytics js 到自定義域名的用戶
@ -195,33 +198,126 @@ preload: {
}
```
## 更多配置
除了配置文件 `src/config.ts` 外,還有部分配置項位於其它文件中。
### 語法高亮
代碼塊的語法高亮主題。
```ts
// astro.config.ts
shikiConfig: {
// 可選主題https://shiki.style/themes
// 背景色默認跟隨部落格主題,而非語法高亮主題
themes: {
light: 'github-light' // 亮色主題
dark: 'github-dark' // 暗色主題
}
}
```
### 文章摘要
文章自動摘要的字元數量。
```ts
// src/utils/description.ts
const EXCERPT_LENGTHS: Record<ExcerptScene, {
cjk: number // 中文、日文、韓文
other: number // 其他語言
}> = {
list: { // 首頁文章列表
cjk: 120, // 自動摘要前 120 字
other: 240, // 自動摘要前 240 字
},
}
```
### 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
getImageOptions: (_path, page) => ({
logo: {
path: './public/icons/og-logo.png', // 本地路徑的 PNG 圖片
size: [250], // logo 寬度
},
font: {
title: { // 標題
families: ['Noto Sans SC'], // 字體
weight: 'Bold', // 字重
color: [34, 33, 36], // 顏色
lineHeight: 1.5, // 行高
},
},
fonts: [ // 字體路徑(本地或遠程)
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Bold.otf',
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Regular.otf',
],
bgGradient: [[242, 241, 245]], // 背景色
// 更多配置https://github.com/delucis/astro-og-canvas/tree/latest/packages/astro-og-canvas
})
```
### RSS 訂閱
[RSS 訂閱頁](https://retypeset.radishzz.cc/zh-tw/rss.xml) 配色。
```html
<!-- public/feeds/xxx-style.xsl -->
<style type="text/css">
body{color:oklch(25% 0.005 298)} /* 字體顏色 */
.bg-white{background-color:oklch(0.96 0.005 298)!important} /* 背景顏色 */
.text-gray{color:oklch(0.25 0.005 298 / 75%)!important} /* 次要字體顏色 */
</style>
```
## 創建新文章
`src/content/posts/` 目錄中新建以 `.md``.mdx` 為後綴的文件,並在文件頂部添加 Front Matter 元數據。
執行 `pnpm new-post <filename>` 創建新文章,可在 `src/content/posts/` 目錄中編輯。
```bash
pnpm new-post -> src/content/posts/new-post.md
pnpm new-post first-post -> src/content/posts/first-post.md
pnpm new-post 2025/03/first-post -> src/content/posts/2025/03/first-post.md
pnpm new-post first-post.mdx -> src/content/posts/first-post.mdx
```
### Front Matter
```markdown
`title``published` 為必填項,其餘配置均可安全刪除。
```md
---
# 必填
title: 主題上手指南
published: 2025-01-26
# 可選
description: 自動選取文章前 120 字作為描述。
description: 自動選取文章前 120 字作為摘要
updated: 2025-03-26
tags: ["部落格主題", "指南"]
tags:
- 部落格主題
- 指南
# 進階,可選
draft: true/false
pin: 1-99
pin: 0-99
toc: true/false
lang: zh/zh-tw/ja/en/es/ru
lang: de/en/es/fr/ja/ko/pl/pt/ru/zh/zh-tw
abbrlink: theme-guide
---
```
### 進階配置介紹
### 進階配置
#### draft
@ -233,7 +329,7 @@ abbrlink: theme-guide
#### toc
是否生成目錄。預設為 true
是否生成目錄。顯示 h2 至 h4 標題。預設由全域配置項 `global.toc` 決定,可在文章中單獨設定以覆蓋全域配置
#### lang
@ -245,20 +341,20 @@ abbrlink: theme-guide
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/apple.md -> example.com/es/posts/apple/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/apple.md -> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink
自定義文章 URL。
自定義文章 URL。只能包含小寫字母、數字和連字符 `-`
```md
# src/config.ts
@ -276,7 +372,3 @@ src/content/posts/apple.md -> example.com/es/posts/banana/
src/content/posts/guide/apple.md -> example.com/es/posts/banana/
src/content/posts/2025/03/apple.md -> example.com/es/posts/banana/
```
### 自動化配置介紹
自動計算文章閱讀時間。自動為每篇文章生成 Open Graph 圖片。相同 abbrlink 的文章會自動共享 Waline 評論,且不受 lang 配置影響。

View file

@ -1,18 +1,20 @@
---
title: 主题上手指南
published: 2025-01-26
updated: 2025-03-12
tags: [博客主题, 指南]
updated: 2025-04-13
tags:
- 博客主题
- 指南
pin: 99
lang: zh
abbrlink: theme-guide
---
Retypeset 是一款基于 [Astro](https://astro.build/) 框架的静态博客主题,中文名为重新编排。本主题以 [活版印字](https://astro-theme-typography.vercel.app/) 为设计灵感,通过建立全新的视觉规范,对所有页面进行重新编排,打造纸质书页般的阅读体验,再现版式之美。所见皆为细节,方寸尽显优雅
Retypeset 是一款基于 [Astro](https://astro.build/) 框架的静态博客主题,中文名为重新编排。本文为 Retypeset 主题上手指南,主要介绍如何修改主题配置与创建新文章,来帮助你快速搭建个人博客
## 主题配置
以下为 Retypeset 的主题配置介绍。通过修改配置文件 [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) 来自定义你的博客。
通过修改配置文件 [src/config.ts](https://github.com/radishzzz/astro-theme-retypeset/blob/master/src/config.ts) 来自定义你的博客。
### 站点信息
@ -22,9 +24,9 @@ site: {
title: 'Retypeset'
// 站点副标题
subtitle: 'Revive the beauty of typography'
// 站点介绍
// 站点描述
description: 'Retypeset is a static blog theme...'
// 使用 src/i18n/ui.ts 中的多语言标题/副标题/站点描述,替换以上静态配置
// 使用 src/i18n/ui.ts 中的多语言标题/副标题/站点描述,代替上方静态配置
i18nTitle: true // true, false
// 作者名称
author: 'radishzz'
@ -32,7 +34,7 @@ site: {
url: 'https://retypeset.radishzz.cc'
// 站点图标
// 推荐格式: svg, png, ico
favicon: '/icon/favicon.svg' // 或 https://example.com/favicon.svg
favicon: '/icons/favicon.svg' // 或 https://example.com/favicon.svg
}
```
@ -56,10 +58,8 @@ color: {
// 暗色模式
dark: {
// 高亮颜色
// 用于站点标题、鼠标悬停效果等
primary: 'oklch(92% 0.005 298)'
// 次要颜色
// 用于普通文本
secondary: 'oklch(77% 0.005 298)'
// 背景色
background: 'oklch(22% 0.005 298)'
@ -72,24 +72,28 @@ color: {
```ts
global: {
// 默认语言
// 站点根路径 / 的语言
locale: 'zh' // zh, zh-tw, ja, en, es, ru
// 站点根路径 '/' 的语言
locale: 'zh' // de, en, es, fr, ja, ko, pl, pt, ru, zh, zh-tw
// 更多语言
// 生成 /ja/' '/en/ 等多语言路径
// 生成 '/en/' '/es/' 等多语言路径
// 不要重复填写默认语言,可以为空 []
moreLocales: ['zh-tw', 'ja', 'en', 'es', 'ru'] // ['zh', 'zh-tw', 'ja', 'en', 'es', 'ru']
moreLocales: ['en', 'es', 'ja', 'ru', 'zh-tw'] // ['de', 'en', 'es', 'fr', 'ja', 'ko', 'pl', 'pt', 'ru', 'zh', 'zh-tw']
// 字体样式
fontStyle: 'sans' // sans, serif
// 文章日期格式
dateFormat: 'YYYY-MM-DD' // YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// 标题与副标题之间的距离
titleGap: 2 // 1, 2, 3
// YYYY-MM-DD, MM-DD-YYYY, DD-MM-YYYY, MONTH DAY YYYY, DAY MONTH YYYY
// 2025-04-13, 04-13-2025, 13-04-2025, Apr 13 202513 Apr 2025
dateFormat: 'YYYY-MM-DD'
// 默认为所有文章开启目录
toc: true // true, false
// 启用 KaTeX 数学公式渲染
katex: true // true, false
// 减少动画和过渡效果以提高性能
reduceMotion: false // true, false
}
```
### 评论服务
### 评论系统
```ts
comment: {
@ -156,23 +160,23 @@ footer: {
links: [
{
name: 'RSS',
url: '/rss.xml', // rss.xml, atom.xml
url: '/atom.xml', // 或 /rss.xml
},
{
name: 'GitHub',
url: 'https://github.com/radishzzz/astro-theme-retypeset',
},
{
name: 'Twitter',
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,9 +186,8 @@ footer: {
preload: {
// 链接预加载策略
linkPrefetch: 'viewport' // hover, tap, viewport, load
// 评论服务器地址
commentURL: 'https://retypeset-comment.radishzz.cc'
// 图床地址
// 优化 Markdown 文件中的远程图片以避免布局抖动
imageHostURL: 'https://image.radishzz.cc'
// 定制 google analytics js
// 适用于路由 google analytics js 到自定义域名的用户
@ -195,33 +198,126 @@ preload: {
}
```
## 更多配置
除了配置文件 `src/config.ts` 外,还有部分配置项位于其它文件中。
### 语法高亮
代码块的语法高亮主题。
```ts
// astro.config.ts
shikiConfig: {
// 可选主题https://shiki.style/themes
// 背景色固定跟随博客主题,而非语法高亮主题
themes: {
light: 'github-light' // 亮色主题
dark: 'github-dark' // 暗色主题
}
}
```
### 文章摘要
文章自动摘要的字符数量。
```ts
// src/utils/description.ts
const EXCERPT_LENGTHS: Record<ExcerptScene, {
cjk: number // 中文、日文、韩文
other: number // 其他语言
}> = {
list: { // 首页文章列表
cjk: 120, // 自动摘要前 120 字
other: 240, // 自动摘要前 240 字
},
}
```
### 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
getImageOptions: (_path, page) => ({
logo: {
path: './public/icons/og-logo.png', // 本地路径的 PNG 图片
size: [250], // logo 宽度
},
font: {
title: { // 标题
families: ['Noto Sans SC'], // 字体
weight: 'Bold', // 字重
color: [34, 33, 36], // 颜色
lineHeight: 1.5, // 行高
},
},
fonts: [ // 字体路径(本地或远程)
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Bold.otf',
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Regular.otf',
],
bgGradient: [[242, 241, 245]], // 背景色
// 更多配置https://github.com/delucis/astro-og-canvas/tree/latest/packages/astro-og-canvas
})
```
### RSS 订阅
[RSS 订阅页](https://retypeset.radishzz.cc/rss.xml) 配色。
```html
<!-- public/feeds/xxx-style.xsl -->
<style type="text/css">
body{color:oklch(25% 0.005 298)} /* 字体颜色 */
.bg-white{background-color:oklch(0.96 0.005 298)!important} /* 背景颜色 */
.text-gray{color:oklch(0.25 0.005 298 / 75%)!important} /* 次要字体颜色 */
</style>
```
## 创建新文章
`src/content/posts/` 目录中新建以 `.md``.mdx` 为后缀的文件,并在文件顶部添加 Front Matter 元数据。
执行 `pnpm new-post <filename>` 创建新文章,可在 `src/content/posts/` 目录中编辑。
```bash
pnpm new-post -> src/content/posts/new-post.md
pnpm new-post first-post -> src/content/posts/first-post.md
pnpm new-post 2025/03/first-post -> src/content/posts/2025/03/first-post.md
pnpm new-post first-post.mdx -> src/content/posts/first-post.mdx
```
### Front Matter
```markdown
`title``published` 为必填项,其余配置均可安全删除。
```md
---
# 必填
title: 主题上手指南
published: 2025-01-26
# 可选
description: 自动选取文章前 120 字作为描述。
description: 自动选取文章前 120 字作为摘要
updated: 2025-03-26
tags: [博客主题, 指南]
tags:
- 博客主题
- 指南
# 进阶,可选
draft: true/false
pin: 1-99
pin: 0-99
toc: true/false
lang: zh/zh-tw/ja/en/es/ru
lang: de/en/es/fr/ja/ko/pl/pt/ru/zh/zh-tw
abbrlink: theme-guide
---
```
### 进阶配置介绍
### 进阶配置
#### draft
@ -233,7 +329,7 @@ abbrlink: theme-guide
#### toc
是否生成目录。默认为 true
是否生成目录。显示 h2 至 h4 标题。默认由全局配置项 `global.toc` 决定,可在文章中单独设置以覆盖全局配置
#### lang
@ -245,20 +341,20 @@ abbrlink: theme-guide
# moreLocales: ['es', 'ru']
# lang: ''
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
-> example.com/es/posts/apple/
-> example.com/ru/posts/apple/
# lang: en
src/content/posts/apple.md -> example.com/posts/apple/
src/content/posts/apple.md -> example.com/posts/apple/
# lang: es
src/content/posts/apple.md -> example.com/es/posts/apple/
src/content/posts/apple.md -> example.com/es/posts/apple/
# lang: ru
src/content/posts/apple.md -> example.com/ru/posts/apple/
src/content/posts/apple.md -> example.com/ru/posts/apple/
```
#### abbrlink
自定义文章 URL。
自定义文章 URL。只能包含小写字母、数字和连字符 `-`
```md
# src/config.ts
@ -276,7 +372,3 @@ src/content/posts/apple.md -> example.com/es/posts/banana/
src/content/posts/guide/apple.md -> example.com/es/posts/banana/
src/content/posts/2025/03/apple.md -> example.com/es/posts/banana/
```
### 自动化配置介绍
自动计算文章阅读时间。自动为每篇文章生成 Open Graph 图片。相同 abbrlink 的文章会自动共享 Waline 评论,且不受 lang 配置影响。

View file

@ -1,22 +1,32 @@
// Global Language Map
export const langMap: Record<string, string[]> = {
'zh': ['zh-CN'],
'zh-tw': ['zh-TW'],
'ja': ['ja-JP'],
'de': ['de-DE'],
'en': ['en-US'],
'es': ['es-ES'],
'fr': ['fr-FR'],
'ja': ['ja-JP'],
'ko': ['ko-KR'],
'pl': ['pl-PL'],
'pt': ['pt-BR'],
'ru': ['ru-RU'],
'zh': ['zh-CN'],
'zh-tw': ['zh-TW'],
}
// Waline Language Map
// https://waline.js.org/guide/i18n.html
// https://waline.js.org/en/guide/features/i18n.html
export const walineLocaleMap: Record<string, string> = {
'de': 'en-US', // fallback to English
'en': 'en-US',
'es': 'es',
'fr': 'fr-FR',
'ja': 'jp-JP',
'ko': 'en-US', // fallback to English
'pl': 'en-US', // fallback to English
'pt': 'pt-BR',
'ru': 'ru-RU',
'zh': 'zh-CN',
'zh-tw': 'zh-TW',
'ja': 'jp-JP', // Waline uses jp-JP not ja-JP
'en': 'en-US',
'es': 'es-ES',
'ru': 'ru-RU',
}
export const giscusLocaleMap: Record<string, string> = {

View file

@ -1,30 +1,12 @@
export const ui = {
'zh': {
title: '重新编排',
subtitle: '再现版式之美',
description: 'Retypeset是一款基于Astro框架的静态博客主题中文名为重新编排。本主题以活版印字为设计灵感通过建立全新的视觉规范对所有页面进行重新编排打造纸质书页般的阅读体验再现版式之美。所见皆为细节方寸尽显优雅。',
posts: '文章',
tags: '标签',
about: '关于',
toc: '目录',
},
'zh-tw': {
title: '重新編排',
subtitle: '再現版式之美',
description: 'Retypeset是一款基於Astro框架的靜態部落格主題中文名為重新編排。本主題以活版印字為設計靈感通過建立全新的視覺規範對所有頁面進行重新編排打造紙質書頁般的閱讀體驗再現版式之美。所見皆為細節方寸盡顯優雅。',
posts: '文章',
tags: '標籤',
about: '關於',
toc: '目錄',
},
'ja': {
title: '再組版',
subtitle: '印刷の美を甦らせる',
description: 'Retypesetは、日本語では「再組版」と呼ばれる、Astroフレームワークをベースにした静的ブログテーマです。活版印字からデザインのインスピレーションを得て、新しい視覚的な規範を確立し、すべてのページのレイアウトを再構成することで、紙の書籍のような読書体験を提供し、版面の美しさを蘇らせます。見るものすべてが細部にこだわり、限られたスペースの中に優雅さを表現しています。',
posts: '記事',
tags: 'タグ',
about: '概要',
toc: '目次',
'de': {
title: 'Neusatz',
subtitle: 'Die Schönheit der Typografie wiederbeleben',
description: 'Retypeset ist ein statisches Blog-Theme basierend auf dem Astro-Framework, auf Deutsch bekannt als "Neusatz". Dieses Theme, inspiriert von traditioneller Typografie, etabliert einen neuen visuellen Standard und gestaltet alle Seiten neu, um ein Leseerlebnis ähnlich dem gedruckter Bücher zu schaffen und die Schönheit des Satzes wiederzubeleben. Jedes Element ist bis ins kleinste Detail durchdacht, Eleganz zeigt sich auch im kleinsten Raum.',
posts: 'Beiträge',
tags: 'Schlagwörter',
about: 'Über',
toc: 'Inhaltsverzeichnis',
},
'en': {
title: 'Retypeset',
@ -44,6 +26,51 @@ export const ui = {
about: 'Sobre',
toc: 'Índice',
},
'fr': {
title: 'Retypographie',
subtitle: 'Raviver la beauté de la typographie',
description: 'Retypeset est un thème de blog statique basé sur le framework Astro, connu en français sous le nom de "Retypographie". Ce thème, inspiré par la typographie traditionnelle, établit une nouvelle norme visuelle et réorganise toutes les pages pour créer une expérience de lecture semblable à celle des livres imprimés, ravivant ainsi la beauté de la mise en page. Chaque élément est soigné dans les moindres détails, l\'élégance se manifeste dans les plus petits espaces.',
posts: 'Articles',
tags: 'Étiquettes',
about: 'À propos',
toc: 'Table des matières',
},
'ja': {
title: '再組版',
subtitle: '印刷の美を甦らせる',
description: 'Retypesetは、日本語では「再組版」と呼ばれる、Astroフレームワークをベースにした静的ブログテーマです。活版印字からデザインのインスピレーションを得て、新しい視覚的な規範を確立し、すべてのページのレイアウトを再構成することで、紙の書籍のような読書体験を提供し、版面の美しさを蘇らせます。見るものすべてが細部にこだわり、限られたスペースの中に優雅さを表現しています。',
posts: '記事',
tags: 'タグ',
about: '概要',
toc: '目次',
},
'ko': {
title: '재조판',
subtitle: '판형의 아름다움을 재현하다',
description: 'Retypeset은 Astro 프레임워크를 기반으로 한 정적 블로그 테마로, 한국어로는 "재조판"이라고 합니다. 이 테마는 활판 인쇄에서 디자인 영감을 얻어, 새로운 시각적 기준을 확립하고 모든 페이지를 재구성하여 종이책과 같은 독서 경험을 제공하며 판형의 아름다움을 되살립니다. 모든 것이 세부적인 디테일이며, 작은 공간에서도 우아함이 느껴집니다.',
posts: '게시물',
tags: '태그',
about: '소개',
toc: '목차',
},
'pl': {
title: 'Przeskład',
subtitle: 'Ożywiając piękno typografii',
description: 'Retypeset to statyczny motyw bloga oparty na frameworku Astro, w języku polskim znany jako "Przeskład". Ten motyw, inspirowany typografią drukarską, ustanawia nowy standard wizualny i reorganizuje wszystkie strony, tworząc doświadczenie czytelnicze przypominające papierowe książki, przywracając piękno układu tekstu. Każdy element jest dopracowany w szczegółach, elegancja zawarta w najmniejszej przestrzeni.',
posts: 'Artykuły',
tags: 'Tagi',
about: 'O stronie',
toc: 'Spis treści',
},
'pt': {
title: 'Retipografia',
subtitle: 'Reviva a beleza da tipografia',
description: 'Retypeset é um tema de blog estático baseado no framework Astro. Inspirado pela tipografia, o Retypeset estabelece um novo padrão visual e reimagina o layout de todas as páginas, criando uma experiência de leitura reminiscente de livros físicos, revivendo a beleza da tipografia. Cada detalhe é visível, elegância em cada espaço.',
posts: 'Artigos',
tags: 'Tags',
about: 'Sobre',
toc: 'Sumário',
},
'ru': {
title: 'Переверстка',
subtitle: 'Возрождая красоту типографики',
@ -53,4 +80,22 @@ export const ui = {
about: 'О себе',
toc: 'Оглавление',
},
'zh': {
title: '重新编排',
subtitle: '再现版式之美',
description: 'Retypeset是一款基于Astro框架的静态博客主题中文名为重新编排。本主题以活版印字为设计灵感通过建立全新的视觉规范对所有页面进行重新编排打造纸质书页般的阅读体验再现版式之美。所见皆为细节方寸尽显优雅。',
posts: '文章',
tags: '标签',
about: '关于',
toc: '目录',
},
'zh-tw': {
title: '重新編排',
subtitle: '再現版式之美',
description: 'Retypeset是一款基於Astro框架的靜態部落格主題中文名為重新編排。本主題以活版印字為設計靈感通過建立全新的視覺規範對所有頁面進行重新編排打造紙質書頁般的閱讀體驗再現版式之美。所見皆為細節方寸盡顯優雅。',
posts: '文章',
tags: '標籤',
about: '關於',
toc: '目錄',
},
}

View file

@ -1,9 +1,10 @@
---
import { ClientRouter } from 'astro:transitions'
import katexCSS from 'katex/dist/katex.min.css?url'
import photoSwipeCSS from 'photoswipe/style.css?url'
import { allLocales, defaultLocale, themeConfig } from '@/config'
import { ui } from '@/i18n/ui'
import { getPageInfo } from '@/utils/page'
import { ClientRouter } from 'astro:transitions'
import katexCSS from 'katex/dist/katex.min.css?url'
interface Props {
postTitle?: string
@ -18,10 +19,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 = '', imageHostURL = '', customGoogleAnalyticsJS = '', customUmamiAnalyticsJS = '' } = themeConfig.preload
const { customGoogleAnalyticsJS = '', customUmamiAnalyticsJS = '' } = themeConfig.preload
const initMetaTheme = mode === 'dark' ? darkMode : lightMode
const siteTitle = i18nTitle ? currentUI.title : title
@ -51,14 +53,17 @@ const pageImage = postSlug
<meta name="theme-color" content={initMetaTheme} />
<!-- Preload -->
<link rel="preload" href="/font/Snell-Black.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/font/EarlySummer-Subset.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/font/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} />}
{imageHostURL && <link rel="preconnect" href={imageHostURL} crossorigin />}
{imageHostURL && <link rel="dns-prefetch" href={imageHostURL} />}
<link rel="preload" href="/fonts/EarlySummer-VF-Split/EarlySummer-VF-Subset.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/fonts/Snell-Black-SF.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/fonts/Snell-Bold-SF.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/fonts/STIX-VF.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href="/fonts/STIX-Italic-VF.woff2" as="font" type="font/woff2" crossorigin />
<link rel="preload" href={photoSwipeCSS} as="style" />
{katexEnabled && <link rel="preload" href={katexCSS} as="style" />}
{commentEnabled && walineServerURL && <link rel="preload" href="/vendors/waline/waline.css" as="style" />}
<link rel="stylesheet" href={photoSwipeCSS} media="print" onload={`this.media='all'`} />
{katexEnabled && <link rel="stylesheet" href={katexCSS} media="print" onload={`this.media='all'`} />}
{commentEnabled && walineServerURL && <link rel="stylesheet" href="/vendors/waline/waline.css" media="print" onload={`this.media='all'`} />}
<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" />
@ -73,22 +78,14 @@ const pageImage = postSlug
/>
))}
<!-- Facebook Open Graph -->
<!-- Open Graph -->
<meta property="og:type" content={postTitle ? 'article' : 'website'} />
<meta property="og:site_name" content={title} />
<meta property="og:url" content={Astro.url} />
<meta property="og:title" content={pageTitle} />
<meta property="og:description" content={pageDescription} />
<meta property="og:url" content={Astro.url} />
<meta property="og:image" content={pageImage} />
<meta property="og:logo" content={favicon} />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
{twitterID && <meta name="twitter:site" content={twitterID} />}
{twitterID && <meta name="twitter:creator" content={twitterID} />}
<meta name="twitter:title" content={pageTitle} />
<meta name="twitter:description" content={pageDescription} />
<meta name="twitter:image" content={pageImage} />
<!-- Site Verification -->
{google && <meta name="google-site-verification" content={google} />}
@ -121,7 +118,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)
}
@ -146,6 +143,8 @@ window
</script>
<!-- Google Analytics -->
<!-- Define gtag on window object for proper Partytown forwarding -->
<!-- See https://github.com/QwikDev/partytown/issues/382 -->
{googleAnalyticsID && (
<>
<script
@ -159,18 +158,18 @@ window
define:vars={{ googleAnalyticsID, customGoogleAnalyticsJS }}
>
window.dataLayer = window.dataLayer || []
function gtag(...args) {
dataLayer.push(args)
window.gtag = function () {
// eslint-disable-next-line prefer-rest-params
dataLayer.push(arguments)
}
gtag('js', new Date())
window.gtag('js', new Date())
if (customGoogleAnalyticsJS) {
gtag('config', googleAnalyticsID, {
window.gtag('config', googleAnalyticsID, {
transport_url: new URL(customGoogleAnalyticsJS).origin,
})
}
else {
gtag('config', googleAnalyticsID)
window.gtag('config', googleAnalyticsID)
}
</script>
</>

View file

@ -3,13 +3,18 @@ import Button from '@/components/Button.astro'
import Footer from '@/components/Footer.astro'
import Header from '@/components/Header.astro'
import Navbar from '@/components/Navbar.astro'
import Scrollbar from '@/components/Widgets/Scrollbar.astro'
import CodeCopyButton from '@/components/Widgets/CodeCopyButton.astro'
import GithubCard from '@/components/Widgets/GithubCard.astro'
import GsapAnimation from '@/components/Widgets/GsapAnimation.astro'
import PhotoSwipe from '@/components/Widgets/PhotoSwipe.astro'
import themeConfig from '@/config'
import Head from '@/layouts/Head.astro'
import { getPageInfo } from '@/utils/page'
import '@/styles/extend.css'
import '@/styles/font.css'
import '@/styles/global.css'
import '@/styles/heti.css'
import '@/styles/markdown.css'
import '@/styles/transition.css'
interface Props {
postTitle?: string
@ -21,23 +26,26 @@ interface Props {
const { postTitle, postDescription, postSlug, supportedLangs = [] } = Astro.props
const { isPost } = getPageInfo(Astro.url.pathname)
const fontStyle = themeConfig.global.fontStyle === 'serif' ? 'font-serif' : 'font-sans'
const showAnimation = !themeConfig.global.reduceMotion
const MarginBottom = isPost && themeConfig.comment?.enabled
? 'mb-10' // Post page with comment system
: 'mb-12' // Other pages
? '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
class:list={[
fontStyle,
{ 'scroll-smooth': isPost },
{ 'reduce-motion': themeConfig.global.reduceMotion },
]}
>
<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 max-w-[min(calc(75vw-16rem),44rem)] mx-[max(5.625rem,calc(50vw-34.375rem))] my-20"
p="x-[min(7.25vw,3.731rem)] y-10"
lg="mx-[max(5rem,calc(50vw-35rem))] my-20 max-w-[min(calc(75vw-16rem),44rem)] min-h-full p-0"
>
<Header />
<Navbar />
@ -46,7 +54,10 @@ const MarginBottom = isPost && themeConfig.comment?.enabled
</main>
<Footer />
</div>
<Scrollbar />
{showAnimation && <GsapAnimation />}
<Button supportedLangs={supportedLangs} />
<CodeCopyButton />
<PhotoSwipe />
<GithubCard />
</body>
</html>

View file

@ -5,6 +5,16 @@ import Layout from '@/layouts/Layout.astro'
<Layout>
<!-- Decorative Line -->
<div class="uno-decorative-line"></div>
<!-- 404 -->
<h1 class="mt-10 text-8 font-title">404</h1>
<!-- Page Not Found -->
<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>

View file

@ -1,7 +1,7 @@
---
import { getCollection, render } from 'astro:content'
import { defaultLocale, moreLocales } from '@/config'
import Layout from '@/layouts/Layout.astro'
import { getCollection, render } from 'astro:content'
export async function getStaticPaths() {
type PathItem = {

View file

@ -1,15 +1,15 @@
---
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'
import Layout from '@/layouts/Layout.astro'
import { checkPostSlugDuplication } from '@/utils/content'
import { generateDescription } from '@/utils/description'
import { getCollection, render } from 'astro:content'
export async function getStaticPaths() {
const posts = await getCollection('posts')
@ -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
class="mb-16.3 block c-primary font-time"
id="gsap-post-page-date"
class="mb-17.2 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,7 +137,9 @@ 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 -->

View file

@ -1,9 +1,9 @@
---
import PostList from '@/components/PostList.astro'
import { allLocales, defaultLocale, moreLocales } from '@/config'
import { defaultLocale, moreLocales } from '@/config'
import { getTagPath } from '@/i18n/path'
import Layout from '@/layouts/Layout.astro'
import { getAllTags, getPostsByTag } from '@/utils/content'
import { getAllTags, getPostsByTag, getTagSupportedLangs } from '@/utils/content'
export async function getStaticPaths() {
type PathItem = {
@ -39,17 +39,7 @@ export async function getStaticPaths() {
const { tag, lang } = Astro.props
const posts = await getPostsByTag(tag, lang)
const allTags = await getAllTags(lang)
// Check if tag has posts in each language, return language code if exists, null if not
const tagSupportedLangs = await Promise.all(
allLocales.map(async (locale) => {
const postsInLang = await getPostsByTag(tag, locale)
return postsInLang.length > 0 ? locale : null
}),
)
// Filter to get supported languages
const supportedLangs = tagSupportedLangs.filter(Boolean) as string[]
const supportedLangs = await getTagSupportedLangs(tag)
---
<Layout supportedLangs={supportedLangs}>
@ -62,7 +52,7 @@ const supportedLangs = tagSupportedLangs.filter(Boolean) as string[]
href={getTagPath(tagName, lang)}
class={`uno-tags-style ${
tag === tagName
? 'border-secondary/75 text-primary'
? 'border-secondary/80 text-primary'
: ''
}`}
>

View file

@ -1,6 +1,6 @@
import type { APIContext } from 'astro'
import { moreLocales } from '@/config'
import { generateRSS } from '@/utils/rss'
import { generateAtom } from '@/utils/feed'
export function getStaticPaths() {
return moreLocales.map(lang => ({
@ -8,7 +8,6 @@ export function getStaticPaths() {
}))
}
export async function GET({ params }: APIContext) {
const lang = params.lang as typeof moreLocales[number]
return generateRSS({ lang })
export async function GET(context: APIContext) {
return generateAtom(context)
}

View file

@ -1,6 +1,6 @@
import type { APIContext } from 'astro'
import { moreLocales } from '@/config'
import { generateRSS } from '@/utils/rss'
import { generateRSS } from '@/utils/feed'
export function getStaticPaths() {
return moreLocales.map(lang => ({
@ -8,7 +8,6 @@ export function getStaticPaths() {
}))
}
export async function GET({ params }: APIContext) {
const lang = params.lang as typeof moreLocales[number]
return generateRSS({ lang })
export async function GET(context: APIContext) {
return generateRSS(context)
}

View file

@ -1,5 +1,6 @@
import { generateRSS } from '@/utils/rss'
import type { APIContext } from 'astro'
import { generateAtom } from '@/utils/feed'
export async function GET() {
return generateRSS()
export async function GET(context: APIContext) {
return generateAtom(context)
}

View file

@ -1,7 +1,7 @@
import type { CollectionEntry } from 'astro:content'
import { generateDescription } from '@/utils/description'
import { OGImageRoute } from 'astro-og-canvas'
import { getCollection } from 'astro:content'
import { generateDescription } from '@/utils/description'
// eslint-disable-next-line antfu/no-top-level-await
const blogEntries = await getCollection('posts')
@ -25,7 +25,7 @@ export const { getStaticPaths, GET } = OGImageRoute({
title: page.title,
description: page.description,
logo: {
path: './public/icon/og-logo.png', // Required local path and PNG format
path: './public/icons/og-logo.png', // Required local path and PNG format
size: [250],
},
border: {
@ -46,10 +46,10 @@ export const { getStaticPaths, GET } = OGImageRoute({
},
},
fonts: [
'https://raw.githubusercontent.com/notofonts/noto-cjk/main/Sans/SubsetOTF/SC/NotoSansSC-Bold.otf',
'https://raw.githubusercontent.com/notofonts/noto-cjk/main/Sans/SubsetOTF/SC/NotoSansSC-Regular.otf',
// 'https://raw.githubusercontent.com/notofonts/noto-cjk/main/Serif/SubsetOTF/SC/NotoSerifSC-Bold.otf',
// 'https://raw.githubusercontent.com/notofonts/noto-cjk/main/Serif/SubsetOTF/SC/NotoSerifSC-Regular.otf',
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Bold.otf',
'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Sans/SubsetOTF/SC/NotoSansSC-Regular.otf',
// 'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Serif/SubsetOTF/SC/NotoSerifSC-Bold.otf',
// 'https://cdn.jsdelivr.net/gh/notofonts/noto-cjk@main/Serif/SubsetOTF/SC/NotoSerifSC-Regular.otf',
],
bgGradient: [[242, 241, 245]],
}),

View file

@ -1,5 +1,6 @@
import { generateRSS } from '@/utils/rss'
import type { APIContext } from 'astro'
import { generateRSS } from '@/utils/feed'
export async function GET() {
return generateRSS()
export async function GET(context: APIContext) {
return generateRSS(context)
}

View file

@ -0,0 +1,37 @@
import { SKIP, visit } from 'unist-util-visit'
export function rehypeCodeCopyButton() {
return (tree) => {
visit(tree, 'element', (node, index, parent) => {
if (
node.tagName === 'pre'
&& node.children?.[0]?.tagName === 'code'
&& parent
&& !node.properties?.['data-copy-button-added']
) {
node.properties = node.properties || {}
node.properties['data-copy-button-added'] = 'true'
parent.children[index] = {
type: 'element',
tagName: 'div',
properties: { className: ['code-block-wrapper'] },
children: [
{
type: 'element',
tagName: 'button',
properties: {
'className': ['code-copy-button'],
'type': 'button',
'aria-label': 'Copy code',
},
children: [],
},
node,
],
}
return SKIP
}
})
}
}

View file

@ -0,0 +1,30 @@
import { visit } from 'unist-util-visit'
export function rehypeImgToFigure() {
return (tree) => {
visit(tree, 'element', (node) => {
if (
node.tagName === 'p'
&& node.children
&& node.children.length === 1
&& node.children[0].tagName === 'img'
&& node.children[0].properties.alt
&& !node.children[0].properties.alt.startsWith('_')
) {
const child = node.children[0]
const altText = child.properties.alt
node.tagName = 'figure'
node.children = [
child,
{
type: 'element',
tagName: 'figcaption',
properties: {},
children: [{ type: 'text', value: altText }],
},
]
}
})
}
}

View 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)
}
}
})
}
}

Some files were not shown because too many files have changed in this diff Show more