SumikaNya

SumikaNya

Shiroテーマに関するいくつかの変更

前言#

こちらでは現在使用しているテーマにいくつかの小さな変更を加え、その内容を記録しています。皆さんの助けになれば幸いです || もし間違っているところがあれば、積極的に議論してください。私は初心者です ||

Warning

提示
変更部分は個人の好みに基づいていますので、異なる意見があればコメント欄で議論してください。

修改顶部导航栏信息展示#

関連ファイルのパスは src\componets\layout\header\config.ts
ファイル内の headerMenuConfig でナビゲーションバーの表示と順序を定義していますので、自分で変更してください。
例えば、こちらでは友リンクを二次から移動しました。
image
image

优化高度过长的图片显示时的页面效果#

画像の高さが過剰に長い場合、ページ全体を占めてしまい、ブラウジング中にページ全体が画像になる可能性があります。過度に高い画像の表示効果は良くないため、CSS の max-height を使用して要素の高さを制限することができます。
src\components\ui\image\ZoomedImage.tsx で以下の部分を見つけ、 max-height max-h-[70vh] w-auto object-contain を追加して、画像の最大高さが 70% を超えないようにします(パラメータは自分で調整可能)、幅は自動調整され、画像は完全に表示され、切り取られません。

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}
画像がページ全体を占めています
70% の制限が追加されました
:::

增强 alert 组件,支持自定义 title#

Shiro が拡張した Markdown 構文に GitHub のアラートが追加されましたが、タイトルの表示は NOTE、IMPORTANT、WARNING、TIP、CAUTION のみに制限されています。
私は Obsidian を使用して Markdown ファイルを編集しており、その中のアラートはカスタムタイトルスタイルをサポートしています。構文は以下の通りです。

> [!WARNING] 任意のタイトルテキスト
> その他のテキスト内容

2025.7.8 の更新で、innei 氏がブロック引用とアラートの処理を更新し、従来の方法は廃止されました!
そこで Claude にファイルの修正を手伝ってもらい、同様の効果を実現しました。
src\components\ui\markdown\parsers\blockquote.tsx

import React, { Children, cloneElement, useMemo, type FC, type ReactNode } from 'react';
import { GitAlert } from './alert';

const getNodeText = (node: ReactNode): string =>
  node == null
    ? ''
    : typeof node === 'string' || typeof node === 'number'
    ? node.toString()
    : Array.isArray(node)
    ? node.map(getNodeText).join('')
    : React.isValidElement<{ children?: ReactNode }>(node)
    ? getNodeText(node.props.children)
    : '';

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 firstText = getNodeText(childrenArray[0]).trim();
    const alertMatch = firstText.match(/^\[!(\w+)\](?:\s(.*))?/);

    if (!alertMatch) return { isAlert: false, alertType: '', title: undefined, content: childrenArray };

    const [_, type, customTitle] = alertMatch;
    const contentNodes = childrenArray.map((child, i) => {
      if (i === 0 && React.isValidElement<{ children?: ReactNode }>(child)) {
        const internalChildren = Children.toArray(child.props.children);
        if (typeof internalChildren[0] === 'string') {
          const text = internalChildren[0].replace(/^\s*\[!(\w+)\]\s*[^\n]*\n?/, '');
          return cloneElement(child, { key: 'first-child-content' }, text, ...internalChildren.slice(1));
        }
      }
      return child;
    });

    return { isAlert: true, alertType: type.toUpperCase(), title: customTitle?.trim(), content: contentNodes };
  }, [children]);

  return isAlert ? (
    <GitAlert type={alertType} title={title}>
      {content}
    </GitAlert>
  ) : (
    <blockquote className={className}>{children}</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>  
  )  
}
折りたたみ内容は過去の処理方法 ```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 {
FluentShieldError 20 Regular,
FluentWarning 28 Regular,
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: FluentWarning 28 Regular,
WARNING: FluentShieldError 20 Regular,
TIP: IonInformation,
CAUTION: FluentShieldError 20 Regular,
}

export const AlertIcon: FC<{
type: keyof typeof typedIconMap
title?: string // 定義 title
}> = ({type, title}) => { //title を追加
const finalType = type || 'NOTE'
const Icon = typedIconMap[finalType] || typedIconMap.NOTE
const typePrefix = title || (finalType [0] + finalType.toLowerCase ().slice (1)) //title があれば title を取得、なければ従来通り

return (
<span
className={clsx('mb-1 inline-flex items-center', textColorMap[finalType])}
>
<Icon
className={clsx(
shrink-0 text-3 xl md: mr-2 md: self-start md: text-left,
typedIconMap[finalType] || typedIconMap.NOTE,
)}
/>

  {typePrefix}
</span>

)
}

/**

  • [!NOTE]

  • ユーザーが考慮すべき情報を強調表示します。
    /
    const ALERT_BLOCKQUOTE_R =
    /^(> \ [!(?NOTE|IMPORTANT|WARNING|TIP|CAUTION)](?.?)) (?<body>(?:\n >.)*)(?=\n {2,}|$)/// 正規表現を修正し、title の取得を追加

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//title を追加
let first = true // 置き換えのロジックを制御し、最初の行は > を除去し、他の行は
に置き換え
const bodyClean = body.replace(/^> */gm, (match: string) => first ? (first = false, '') : '
').trim () // 置き換えロジックを修正

return (
  <blockquote
    className={clsx(borderColorMap[type], 'not-italic')}
    key={state.key}
  >
    <!--title解析を追加し、改行ロジックを調整-->
    <AlertIcon type={type as any} title={title} /> 
    

    <Markdown
      allowsScript
      className="not-prose w-full [&>p:first-child]:mt-0"
    >
      {bodyClean}
    </Markdown>
  </blockquote>
)

},
}

</details>

変更後は以下の効果を実現できます。  

```text
<div />第 1 种

> [!WARNING] 任意のタイトルテキスト
> その他のテキスト内容

<div />第 2 种

> [!NOTE] 任意のタイトルテキスト
> その他のテキスト内容

<div />第 3 种

> [!NOTE]
> 従来の方法
第 1 种

Warning

任意のタイトルテキスト
その他のテキスト内容

第 2 种

Note

任意のタイトルテキスト
その他のテキスト内容

第 3 种

Note

従来の方法

この記事は Mix Space によって xLog に同期更新されました。
元のリンクは https://blog.lolita.best/posts/blog/ShiroModifySumika


読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。