Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 21cb30d

Browse files
committed
feat: auto replace element with geist component
1 parent 67c6c07 commit 21cb30d

File tree

7 files changed

+126
-3
lines changed

7 files changed

+126
-3
lines changed

‎lib/components/mdx/hybrid-code.tsx‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React, { ReactNode, useMemo } from 'react'
2+
import { Code, CodeProps } from '@geist-ui/core'
3+
4+
export type HybridCodeProps = CodeProps
5+
export const FILE_NAME_PREFIX = '// NAME:'
6+
type HybridCodeChildrenAndName = {
7+
children: ReactNode | undefined
8+
name?: string | undefined
9+
}
10+
11+
const extractFileName = (
12+
children: ReactNode | undefined,
13+
stopDeep: boolean = false,
14+
): HybridCodeChildrenAndName => {
15+
if (!children) return { children }
16+
let name: string | undefined = undefined
17+
const next = React.Children.map(children, child => {
18+
if (name) return child
19+
if (!React.isValidElement(child)) return null
20+
const grandson = child.props?.children
21+
if (typeof grandson === 'string' && grandson?.startsWith(FILE_NAME_PREFIX)) {
22+
name = grandson
23+
return null
24+
}
25+
if (!Array.isArray(grandson) || stopDeep) return child
26+
27+
const { children: puredGrandson, name: puredName } = extractFileName(
28+
child.props?.children,
29+
true,
30+
)
31+
if (!puredName) return child
32+
33+
name = puredName
34+
const withoutSpaceAndNull = React.Children.toArray(puredGrandson).filter(
35+
(r, index) => {
36+
if (index === 0 && r === '\n') return false
37+
return !!r
38+
},
39+
)
40+
return React.cloneElement(child, {
41+
children: withoutSpaceAndNull,
42+
})
43+
})
44+
return {
45+
children: next,
46+
name,
47+
}
48+
}
49+
50+
const HybridCode: React.FC<HybridCodeProps> = ({ children }) => {
51+
const { children: withoutNameChildren, name } = useMemo<HybridCodeChildrenAndName>(
52+
() => extractFileName(children),
53+
[children],
54+
)
55+
const withoutPrefixName = useMemo(() => {
56+
if (!name) return name
57+
return name.replace(FILE_NAME_PREFIX, '')
58+
}, [name])
59+
60+
return (
61+
<Code block name={withoutPrefixName}>
62+
{withoutNameChildren}
63+
</Code>
64+
)
65+
}
66+
67+
export default HybridCode

‎lib/components/mdx/hybrid-link.tsx‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import React from 'react'
2+
import NextLink from 'next/link'
3+
import { Link, LinkProps } from '@geist-ui/core'
4+
5+
export type HybridLinkProps = LinkProps
6+
7+
const HybridLink: React.FC<HybridLinkProps> = ({ href = '#', children, ...props }) => {
8+
const isRelativeUrl = !/^([a-z0-9]*:|.{0})\/\/.*$/gim.test(href)
9+
10+
if (isRelativeUrl) {
11+
return (
12+
<NextLink href={href} passHref>
13+
<Link color block {...props}>
14+
{children}
15+
</Link>
16+
</NextLink>
17+
)
18+
}
19+
20+
return (
21+
<Link href={href} target="_blank" color rel="noreferrer nofollow" {...props}>
22+
{children}
23+
</Link>
24+
)
25+
}
26+
27+
export default HybridLink

‎lib/components/mdx/index.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as HybridLink } from './hybrid-link'
2+
export { default as HybridCode } from './hybrid-code'

‎package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"@geist-ui/core": "^2.3.4",
1616
"@geist-ui/icons": "^1.0.1",
1717
"@geist-ui/prism": "^1.1.1",
18+
"@mdx-js/react": "^2.0.0",
1819
"@unix/views": "^0.2.0",
1920
"ms": "^2.1.3",
2021
"next": "^12.1.0",

‎pages/_app.tsx‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import { NextPage } from 'next'
33
import { AppProps } from 'next/app'
44
import BLOG from '../blog.config'
55
import useDomClean from 'lib/use-dom-clean'
6+
import { MDXProvider } from '@mdx-js/react'
67
import { PrismBaseline } from '@geist-ui/prism'
7-
import { GeistProvider, CssBaseline } from '@geist-ui/core'
8+
import { GeistProvider, CssBaseline,Image } from '@geist-ui/core'
89
import { useCallback, useState, useEffect, useMemo } from 'react'
910
import { getDNSPrefetchValue } from 'lib/data-transform'
1011
import { BlogConfigsProvider } from 'lib/components'
12+
import { HybridLink, HybridCode } from 'lib/components/mdx'
1113

1214
const Application: NextPage<AppProps<{}>> = ({ Component, pageProps }) => {
1315
const [themeType, setThemeType] = useState('light')
@@ -58,7 +60,14 @@ const Application: NextPage<AppProps<{}>> = ({ Component, pageProps }) => {
5860
<CssBaseline />
5961
<PrismBaseline />
6062
<BlogConfigsProvider onChange={changeHandle}>
61-
<Component {...pageProps} />
63+
<MDXProvider
64+
components={{
65+
a: HybridLink,
66+
img: Image,
67+
pre: HybridCode,
68+
}}>
69+
<Component {...pageProps} />
70+
</MDXProvider>
6271
</BlogConfigsProvider>
6372
<style global jsx>{`
6473
@media only screen and (max-width: 767px) {

‎typings/mdx.d.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,12 @@ declare module '*.mdx' {
33
export default MDXComponent
44
}
55

6+
declare module "@mdx-js/react" {
7+
import { ComponentType, StyleHTMLAttributes } from "react"
8+
9+
type MDXProps = {
10+
children: React.ReactNode
11+
components: { [key:? string]: React.ReactNode, }
12+
}
13+
export class MDXProvider extends React.Component<MDXProps> {}
14+
}

‎yarn.lock‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,14 @@
308308
unist-util-visit "^4.0.0"
309309
vfile "^5.0.0"
310310

311+
"@mdx-js/react@^2.0.0":
312+
version "2.0.0"
313+
resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-2.0.0.tgz#00a9f5467d2761fe3818222740f50403f83aee2c"
314+
integrity sha512-icpMd43xqORnHSVRwALZv3ELN3IS7VS3BL+FyH2FFergQPSQ21FX0lN+OMIs0X+3dGY1L0DLhBCkMfPO+yDG7Q==
315+
dependencies:
316+
"@types/mdx" "^2.0.0"
317+
"@types/react" ">=16"
318+
311319
"@next/env@12.1.0":
312320
version "12.1.0"
313321
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.0.tgz#73713399399b34aa5a01771fb73272b55b22c314"
@@ -468,7 +476,7 @@
468476
"@types/prop-types" "*"
469477
csstype "^3.0.2"
470478

471-
"@types/react@^17.0.39":
479+
"@types/react@>=16", "@types/react@^17.0.39":
472480
version "17.0.39"
473481
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.39.tgz#d0f4cde092502a6db00a1cded6e6bf2abb7633ce"
474482
integrity sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /