Preface#
Some small modifications have been made to the current theme, recording the changes, hoping to help everyone || If there are any mistakes, please feel free to discuss, I'm a newbie ||
Warning
Tip
The modifications are based on personal preference. If you have different ideas, feel free to discuss in the comments.
Modify the Information Display of the Top Navigation Bar#
The relevant file path is src\components\layout\header\config.ts
The display and order of the navigation bar are defined in the headerMenuConfig in the file, you can modify it as needed.
For example, the friend links have been moved out of the secondary level.
Optimize the Page Effect When Displaying Images with Excessive Height#
If the image height is too long, it will occupy the entire page, which may result in the entire page being an image during browsing. The display effect for excessively tall images is not good. We can limit the height display of the element using max-height
in CSS.
Find the following part in src\components\ui\image\ZoomedImage.tsx
and add max-height max-h-[70vh] w-auto object-contain
to ensure that the maximum height of the image does not exceed 70% (parameters can be adjusted as needed), and the width remains adaptive, allowing the image to be fully displayed without being cropped.
const styles = tv({
base: 'rounded-xl overflow-hidden text-center inline-flex items-center justify-center duration-200 max-height max-h-[70vh] w-auto object-contain',
variants: {
status: {
loading: 'hidden opacity-0',
loaded: 'opacity-100 block',
error: 'hidden opacity-0',
},
},
})
::: grid {cols=2,rows=1,gap=4,type=images}
:::
Enhance the Alert Component to Support Custom Titles#
The markdown syntax extended by Shiro includes GitHub alerts, but it limits the display of titles to only NOTE, IMPORTANT, WARNING, TIP, CAUTION.
Since I use Obsidian to edit Markdown files, the alerts there can support custom title styles, with the syntax as follows:
> [!WARNING] Any title text
> Other text content
On July 8, 2025, Innei updated the handling of blockquotes and alerts, and the original method is now obsolete!
So I used Claude to help modify the file to achieve the same effect.
src\components\ui\markdown\parsers\blockquote.tsx
import React, { Children, cloneElement, useMemo } from 'react';
import type { FC, ReactNode } from 'react';
import { GitAlert } from './alert';
const getNodeText = (node: ReactNode): string => {
if (node == null) return '';
if (typeof node === 'string' || typeof node === 'number') return node.toString();
if (Array.isArray(node)) return node.map(getNodeText).join('');
if (React.isValidElement<{ children?: ReactNode }>(node)) return getNodeText(node.props.children);
return '';
};
export const MBlockQuote: FC<{
className?: string;
children: ReactNode;
alert?: string;
}> = ({ className, children, alert }) => {
if (alert) return <GitAlert type={alert}>{children}</GitAlert>;
const { isAlert, alertType, title, content } = useMemo(() => {
const childrenArray = Children.toArray(children);
const elementChildren = childrenArray.filter(React.isValidElement);
if (elementChildren.length === 0) return { isAlert: false, alertType: '', title: undefined, content: childrenArray };
const firstChild = elementChildren[0];
const alertMatch = getNodeText(firstChild).trim().match(/^\[!(\w+)\](?:\s(.*))?/);
if (!alertMatch) return { isAlert: false, alertType: '', title: undefined, content: childrenArray };
const alertType = alertMatch[1].toUpperCase();
const customTitle = alertMatch[2]?.trim() || undefined;
const contentNodes: ReactNode[] = [];
if (React.isValidElement<{ children?: ReactNode }>(firstChild)) {
const internalChildren = Children.toArray(firstChild.props.children);
if (internalChildren.length > 0 && typeof internalChildren[0] === 'string') {
const contentOnlyText = internalChildren[0].replace(/^\s*\[!(\w+)\]\s*[^\n]*\n?/, '');
const modifiedFirstChild = cloneElement(firstChild, { key: 'first-child-content' }, contentOnlyText, ...internalChildren.slice(1));
contentNodes.push(modifiedFirstChild);
} else {
contentNodes.push(firstChild);
}
}
contentNodes.push(...elementChildren.slice(1));
return { isAlert: true, alertType, title: customTitle, content: contentNodes };
}, [children]);
if (isAlert) {
return (
<GitAlert type={alertType} title={title}>
{content}
</GitAlert>
);
}
return (
<blockquote className={className}>
{content}
</blockquote>
);
};
src\components\ui\markdown\parsers\alert.tsx
CAUTION: FluentShieldError20Regular,
}
const AlertIcon: FC<{
type: keyof typeof typedIconMap
title?: string
}> = ({ type, title }) => {
const finalType = type || 'NOTE'
const Icon = typedIconMap[finalType] || typedIconMap.NOTE
const typePrefix = title || (finalType[0] + finalType.toLowerCase().slice(1));
return (
<span
@@ -57,9 +58,8 @@ export const AlertIcon: FC<{
)
}
export const GitAlert: FC<{ type: string; title?: string; children: React.ReactNode }> = (props) => {
const { type, title, children } = props
const upperType = type.toUpperCase() as keyof typeof borderColorMap
return (
<blockquote
@@ -71,10 +71,10 @@ export const GitAlert = (props: { type: string; text: string }) => {
'not-italic',
)}
>
<AlertIcon type={upperType as any} title={title} />
<br />
{children}
</blockquote>
)
}
The following is the historical processing.
Thus, the regex and parsing for this part have been modified to enhance the display of custom titles. The file path is src\components\ui\markdown\parsers\alert.tsx
.
import clsx from 'clsx'
import type { MarkdownToJSX } from 'markdown-to-jsx'
import { blockRegex, Priority } from 'markdown-to-jsx'
import type { FC } from 'react'
import {
FluentShieldError20Regular,
FluentWarning28Regular,
IonInformation,
} from '~/components/icons/status'
import { Markdown } from '../Markdown'
const textColorMap = {
NOTE: 'text-blue-500 dark:text-blue-400',
IMPORTANT: 'text-accent',
WARNING: 'text-amber-500 dark:text-amber-400',
TIP: 'text-green-500 dark:text-green-400',
CAUTION: 'text-red-500 dark:text-red-400',
} as any
const borderColorMap = {
NOTE: 'before:bg-blue-500 before:bg-blue-400',
IMPORTANT: 'before:bg-accent',
WARNING: 'before:bg-amber-500 dark:before:bg-amber-400',
TIP: 'before:bg-green-500 dark:before:bg-green-400',
CAUTION: 'before:bg-red-500 dark:before:bg-red-400',
} as any
const typedIconMap = {
NOTE: IonInformation,
IMPORTANT: FluentWarning28Regular,
WARNING: FluentShieldError20Regular,
TIP: IonInformation,
CAUTION: FluentShieldError20Regular,
}
export const AlertIcon: FC<{
type: keyof typeof typedIconMap
title?: string // Define title
}> = ({ type, title }) => { // Add title
const finalType = type || 'NOTE'
const Icon = typedIconMap[finalType] || typedIconMap.NOTE
const typePrefix = title || (finalType[0] + finalType.toLowerCase().slice(1)) // If title has value, get title, otherwise keep it the same as before
return (
<span
className={clsx('mb-1 inline-flex items-center', textColorMap[finalType])}
>
<Icon
className={clsx(
`shrink-0 text-3xl md:mr-2 md:self-start md:text-left`,
typedIconMap[finalType] || typedIconMap.NOTE,
)}
/>
{typePrefix}
</span>
)
}
/**
*
* > [!NOTE]
* > Highlights information that users should take into account, even when skimming.
*/
const ALERT_BLOCKQUOTE_R =
/^(> \[!(?<type>NOTE|IMPORTANT|WARNING|TIP|CAUTION)\](?<title>.*?))(?<body>(?:\n *>.*)*)(?=\n{2,}|$)/ // Modify regex to include title retrieval
export const AlertsRule: MarkdownToJSX.Rule = {
match: blockRegex(ALERT_BLOCKQUOTE_R),
order: Priority.HIGH,
parse(capture) {
return {
raw: capture[0],
parsed: {
...capture.groups,
},
} as any
},
react(node, output, state) {
const { type, body, title } = node.parsed // Add title
let first = true // Control the replacement logic for replace, the first line removes >, the rest replace with <br>
const bodyClean = body.replace(/^> */gm, (match: string) => first ? (first = false, '') : '<br>').trim() // Modify replacement logic
return (
<blockquote
className={clsx(borderColorMap[type], 'not-italic')}
key={state.key}
>
<!-- Add title parsing, adjust line break logic -->
<AlertIcon type={type as any} title={title} />
<Markdown
allowsScript
className="not-prose w-full [&>p:first-child]:mt-0"
>
{bodyClean}
</Markdown>
</blockquote>
)
},
}
After the modification, the following effect can be achieved. If there are multiple alerts together, remember to separate them with <div />
.
> [!WARNING] Any title text
> Other text content
> [!NOTE] Any title text
> Other text content
Warning
Any title text
Other text content
Note
Any title text
Other text content
This article is synchronized and updated to xLog by Mix Space.
The original link is https://blog.lolita.best/posts/blog/ShiroModifySumika