Markdown 语法

Markdown 语法在 GFM 中进行了其他扩展。

Alert

此语法是 GFM 的新增的。

> [!NOTE]
> Highlights information that users should take into account, even when skimming.

> [!IMPORTANT]
> Crucial information necessary for users to succeed.

> [!WARNING]
> Critical content demanding immediate user attention due to potential risks.
Note

Highlights information that users should take into account, even when skimming.

Important

Crucial information necessary for users to succeed.

Warning

Critical content demanding immediate user attention due to potential risks.

Notice

::: warning
_here be dragons_
:::

::: banner {error}
_here be dragons_
:::

::: banner {note}
_here be dragons_
:::
here be dragons
here be dragons
here be dragons

对于单独成行的链接,会有做出不用的渲染。

https://github.com/Innei/Shiro
https://twitter.com/zhizijun/status/1649822091234148352?s=20

https://twitter.com/zhizijun/status/1649822091234148352?s=20

https://www.youtube.com/watch?v=N93cTbtLCIM
https://gist.github.com/Innei/94b3e8f078d29e1820813a24a3d8b04e

https://gist.github.com/Innei/94b3e8f078d29e1820813a24a3d8b04e

https://github.com/vuejs/vitepress/commit/71eb11f72e60706a546b756dc3fd72d06e2ae4e2

https://github.com/vuejs/vitepress/commit/71eb11f72e60706a546b756dc3fd72d06e2ae4e2

https://codesandbox.io/s/framer-motion-layoutroot-prop-forked-p39g96
https://github.com/Innei/Shiro/blob/108d4c3e927e1c9c9304e41a0631f91958477d9f/src/providers/root/modal-stack-provider.tsx
'use client'

import * as Dialog from '@radix-ui/react-dialog'
import {
  createElement,
  memo,
  useCallback,
  useEffect,
  useId,
  useMemo,
  useRef,
} from 'react'
import { AnimatePresence, m, useAnimationControls } from 'framer-motion'
import { atom, useAtomValue, useSetAtom } from 'jotai'
import { usePathname } from 'next/navigation'
import type { Target, Transition } from 'framer-motion'
import type { FC, PropsWithChildren, SyntheticEvent } from 'react'

import { CloseIcon } from '~/components/icons/close'
import { DialogOverlay } from '~/components/ui/dialog/DialogOverlay'
import { Divider } from '~/components/ui/divider'
import { microReboundPreset } from '~/constants/spring'
import { useEventCallback } from '~/hooks/common/use-event-callback'
import { useIsClient } from '~/hooks/common/use-is-client'
import { stopPropagation } from '~/lib/dom'
import { clsxm } from '~/lib/helper'
import { jotaiStore } from '~/lib/store'

const modalIdToPropsMap = {} as Record<string, ModalProps>

export type ModalContentComponent<T> = FC<ModalContentPropsInternal & T>
type ModalContentPropsInternal = {
  dismiss: () => void
}

interface ModalProps {
  title: string
  content: FC<ModalContentPropsInternal>
  CustomModalComponent?: FC<PropsWithChildren>
  clickOutsideToDismiss?: boolean
  modalClassName?: string
  modalContainerClassName?: string
}

const modalStackAtom = atom([] as (ModalProps & { id: string })[])

const useDismissAllWhenRouterChange = () => {
  const pathname = usePathname()
  useEffect(() => {
    actions.dismissAll()
  }, [pathname])
}

export const useModalStack = () => {
  const id = useId()
  const currentCount = useRef(0)
  return {
    present(props: ModalProps & { id?: string }) {
      const modalId = `${id}-${currentCount.current++}`
      jotaiStore.set(modalStackAtom, (p) => {
        const modalProps = {
          ...props,
          id: props.id ?? modalId,
        }
        modalIdToPropsMap[modalProps.id] = modalProps
        return p.concat(modalProps)
      })

      return () => {
        jotaiStore.set(modalStackAtom, (p) => {
          return p.filter((item) => item.id !== modalId)
        })
      }
    },

    ...actions,
  }
}

const actions = {
  dismiss(id: string) {
    jotaiStore.set(modalStackAtom, (p) => {
      return p.filter((item) => item.id !== id)
    })
  },
  dismissTop() {
    jotaiStore.set(modalStackAtom, (p) => {
      return p.slice(0, -1)
    })
  },
  dismissAll() {
    jotaiStore.set(modalStackAtom, [])
  },
}
export const ModalStackProvider: FC<PropsWithChildren> = ({ children }) => {
  return (
    <>
      {children}
      <ModalStack />
    </>
  )
}

const ModalStack = () => {
  const stack = useAtomValue(modalStackAtom)

  const isClient = useIsClient()
  useDismissAllWhenRouterChange()
  if (!isClient) return null

  return (
    <AnimatePresence>
      {stack.map((item, index) => {
        return <Modal key={item.id} item={item} index={index} />
      })}
    </AnimatePresence>
  )
}

const enterStyle: Target = {
  scale: 1,
  opacity: 1,
}

const initialStyle: Target = {
  scale: 0.96,
  opacity: 0,
}

const modalTransition: Transition = {
  ...microReboundPreset,
}

const Modal: Component<{
  item: ModalProps & { id: string }
  index: number
}> = memo(function Modal({ item, index }) {
  const setStack = useSetAtom(modalStackAtom)
  const close = useEventCallback(() => {
    setStack((p) => {
      return p.filter((modal) => modal.id !== item.id)
    })
  })

  const onClose = useCallback(
    (open: boolean): void => {
      if (!open) {
        close()
      }
    },
    [close],
  )
  const animateController = useAnimationControls()
  useEffect(() => {
    animateController.start(enterStyle)
  }, [])
  const {
    CustomModalComponent,
    modalClassName,
    content,
    title,
    clickOutsideToDismiss,
    modalContainerClassName,
  } = item
  const modalStyle = useMemo(() => ({ zIndex: 99 + index }), [index])
  const dismiss = useCallback(
    (e: SyntheticEvent) => {
      stopPropagation(e)
      close()
    },
    [close],
  )
  const noticeModal = useCallback(() => {
    animateController
      .start({
        scale: 1.05,
        transition: {
          duration: 0.06,
        },
      })
      .then(() => {
        animateController.start({
          scale: 1,
        })
      })
  }, [animateController])

  const ModalProps: ModalContentPropsInternal = {
    dismiss: close,
  }

  if (CustomModalComponent) {
    return (
      <Dialog.Root open onOpenChange={onClose}>
        <Dialog.Portal>
          <DialogOverlay zIndex={20} />
          <Dialog.Content asChild>
            <div
              className={clsxm(
                'fixed inset-0 z-[20] overflow-auto',
                modalContainerClassName,
              )}
              onClick={clickOutsideToDismiss ? dismiss : undefined}
            >
              <div className="contents" onClick={stopPropagation}>
                <CustomModalComponent>
                  {createElement(content, ModalProps)}
                </CustomModalComponent>
              </div>
            </div>
          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>
    )
  }
  return (
    <Dialog.Root open onOpenChange={onClose}>
      <Dialog.Portal>
        <DialogOverlay zIndex={20} />
        <Dialog.Content asChild>
          <div
            className={clsxm(
              'fixed inset-0 z-[20] flex center',
              modalContainerClassName,
            )}
            onClick={clickOutsideToDismiss ? dismiss : noticeModal}
          >
            <m.div
              style={modalStyle}
              exit={initialStyle}
              initial={initialStyle}
              animate={animateController}
              transition={modalTransition}
              className={clsxm(
                'relative flex flex-col overflow-hidden rounded-lg',
                'bg-slate-50/80 dark:bg-neutral-900/80',
                'p-2 shadow-2xl shadow-stone-300 backdrop-blur-sm dark:shadow-stone-800',
                'max-h-[70vh] min-w-[300px] max-w-[90vw] lg:max-h-[calc(100vh-20rem)] lg:max-w-[70vw]',
                'border border-slate-200 dark:border-neutral-800',
                modalClassName,
              )}
              onClick={stopPropagation}
            >
              <Dialog.Title className="flex-shrink-0 px-4 py-2 text-lg font-medium">
                {title}
              </Dialog.Title>
              <Divider className="my-2 flex-shrink-0 border-slate-200 opacity-80 dark:border-neutral-800" />

              <div className="min-h-0 flex-shrink flex-grow overflow-auto px-4 py-2">
                {createElement(content, ModalProps)}
              </div>

              <Dialog.DialogClose
                onClick={close}
                className="absolute right-0 top-0 z-[9] p-5"
              >
                <CloseIcon />
              </Dialog.DialogClose>
            </m.div>
          </div>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  )
})
https://github.com/Innei/Shiro/pull/129
https://github.com/Innei/Shiro/commit/6957e011439eb2d3cbf42bfb67ed81b07d4bcc2a

https://github.com/Innei/Shiro/commit/6957e011439eb2d3cbf42bfb67ed81b07d4bcc2a

https://trpc.io/docs/client/react/useInfiniteQuery

https://trpc.io/docs/client/react/useInfiniteQuery

[TRPC](https://trpc.io/docs/client/react/useInfiniteQuery)

TRPC

对于内联链接,会根据内置解析增加 Favicon。

Inline [Innei](https://github.com/Innei)

Inline Innei

Inline [pseudoyu](https://twitter.com/pseudo_yu)

Inline pseudoyu

Inline <https://github.com/Innei>

Inline https://github.com/Innei

Inline https://github.com/Innei

Inline https://github.com/Innei

Mention

使用一些 Mention?

[Innei]{GH@Innei}

Innei 太菜了

Spoiler

和删除线有所不同。

Hi, this is ||Spoiler||

Hi, this is Spoiler

KateX

$ c = \pm\sqrt{a^2 + b^2} $

c=±a2+b2c = \pm\sqrt{a^2 + b^2}

$c = \pm\sqrt{a^2 + b^2}$

c=±a2+b2c = \pm\sqrt{a^2 + b^2}

P(x)=anxn+an1xn1++a1x+a0P(x) = a_nx^n+a_{n-1}x^{n-1} + \dots + a_1x + a_0

$P(x) = a_nx^n+a_{n-1}x^{n-1} + \dots + a_1x + a_0$
$$

P\left(U,T\right)=100\left.\left(0.6\min\left(1,\frac{U-0.70}{0.90-0.70}\right)+0.4\min\left(1,\frac{T-4000}{14000-4000}\right)\right)\right.

$$
P(U,T)=100(0.6min(1,U0.700.900.70)+0.4min(1,T4000140004000)) P\left(U,T\right)=100\left.\left(0.6\min\left(1,\frac{U-0.70}{0.90-0.70}\right)+0.4\min\left(1,\frac{T-4000}{14000-4000}\right)\right)\right.

最后更新于 2024/8/15 21:57:42

更新历史

本书还在编写中..

前往 https://innei.in/posts/tech/my-first-nextjs-book-here#comment 发表你的观点吧。