Skip to content

Commit 1068f5b

Browse files
committed
refactor: add types to doc.js & relative files
1 parent c990c6f commit 1068f5b

File tree

12 files changed

+359
-329
lines changed

12 files changed

+359
-329
lines changed

gatsby-theme-oi-wiki/package.json

+3
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@
5858
"use-persisted-state": "^0.3.0"
5959
},
6060
"devDependencies": {
61+
"@types/mark.js": "^8.11.6",
6162
"@types/react-helmet": "^6.1.1",
63+
"@types/use-persisted-state": "^0.3.0",
6264
"@typescript-eslint/eslint-plugin": "^4.28.3",
6365
"@typescript-eslint/parser": "^4.28.3",
6466
"eslint": "^7.29.0",
@@ -69,6 +71,7 @@
6971
"eslint-plugin-react": "^7.24.0",
7072
"eslint-plugin-react-hooks": "^4.1.2",
7173
"gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.24",
74+
"schema-dts": "^0.9.0",
7275
"ts-graphql-plugin": "^2.1.3",
7376
"typescript": "^4.3.5"
7477
},

gatsby-theme-oi-wiki/src/components/doc.js gatsby-theme-oi-wiki/src/components/Mdx.tsx

+40-36
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
1-
import MDRenderer from '../lib/MDRenderer'
2-
import React, { useEffect } from 'react'
1+
import React, { useCallback, useEffect } from 'react'
32
import Mark from 'mark.js'
4-
import Details from './Details.tsx'
5-
import Summary from './Summary.tsx'
6-
import { SmartLink } from './Link'
7-
import SEO from './Seo'
83
import clsx from 'clsx'
4+
5+
import MDRenderer from '../lib/MDRenderer'
6+
import Details from './Details'
7+
import Summary from './Summary'
8+
import { SmartLink, SmartLinkProps } from './Link'
9+
import SEO from './Seo'
910
import StyledLayout from './StyledLayout'
11+
import { DeepRequiredNonNull, DeepWriteable, Nullable } from '../types/common'
12+
import { ReactiveHastComponents } from '../lib/reactiveHast'
13+
14+
export interface MdxProps {
15+
data: DeepWriteable<DeepRequiredNonNull<GatsbyTypes.DocQuery>>
16+
location: Location & { state: Nullable<{ searchKey: string }> };
17+
}
1018

11-
function Mdx ({ data: { mdx }, location }) {
12-
// console.log(mdx);
13-
// const headingTitle = mdx.headings[0] && mdx.headings[0].value
14-
const title = mdx.slug === '/' ? null : mdx.frontmatter.title
19+
const Mdx: React.FC<MdxProps> = ({ data: { mdx }, location }) => {
20+
const title = mdx.fields.slug === '/' ? '' : mdx.frontmatter.title
1521
const description = mdx.frontmatter.description || mdx.excerpt
16-
const authors = mdx.frontmatter.author || null
17-
const tags = mdx.frontmatter.tags || null
18-
const noMeta = mdx.frontmatter.noMeta === 'true' || false
19-
const noComment = mdx.frontmatter.noComment === 'true' || false
20-
const noEdit = mdx.frontmatter.noEdit === 'true' || false
22+
const authors = mdx.frontmatter.author || ''
23+
const tags = mdx.frontmatter.tags || []
24+
const noMeta = mdx.frontmatter.noMeta || false
25+
const noComment = mdx.frontmatter.noComment || false
26+
const noEdit = false
2127
const toc = mdx.toc || null
2228
const relativePath = mdx.parent.relativePath || ''
2329
const modifiedTime = mdx.parent.modifiedTime || ''
@@ -26,21 +32,21 @@ function Mdx ({ data: { mdx }, location }) {
2632
const dateModified = mdx.parent.changeTime || ''
2733
const isIndex = mdx.fields.isIndex
2834

29-
const highlightNode = (tagName, isHighlight) => {
30-
const mainNodes = document.getElementsByTagName('main')
31-
const nodes = mainNodes[0].getElementsByTagName(tagName)
32-
const children = [...nodes]
33-
children.forEach((node) => {
34-
const instance = new Mark(node)
35+
const highlightNode = useCallback((tagName: string, isHighlight: boolean): void => {
36+
if (location.state?.searchKey) {
37+
const mainNodes = document.getElementsByTagName('main')
38+
const nodes = mainNodes[0].querySelectorAll(tagName)
39+
const instance = new Mark(nodes)
3540
instance[isHighlight ? 'mark' : 'unmark'](
3641
location.state.searchKey,
3742
{
3843
exclude: ['span'],
3944
})
40-
})
41-
}
45+
}
46+
}, [location.state?.searchKey])
47+
4248
useEffect(() => {
43-
if (location?.state?.searchKey) {
49+
if (location.state?.searchKey) {
4450
highlightNode('h1', true)
4551
highlightNode('h2', true)
4652
highlightNode('h3', true)
@@ -53,27 +59,25 @@ function Mdx ({ data: { mdx }, location }) {
5359
highlightNode('p', false)
5460
}, 5000)
5561
}
56-
}, [])
62+
}, [highlightNode, location.state?.searchKey])
5763

58-
function LinkGetter () {
59-
return function TooltipLink (props) {
60-
return <SmartLink {...props} pathname={location.pathname} isIndex={isIndex} tooltip={true}/>
61-
}
62-
}
64+
const LinkGetter: React.FC<SmartLinkProps> = (props) =>
65+
<SmartLink {...props} pathname={location.pathname} isIndex={isIndex} tooltip={true}/>
6366

64-
function InlineCode ({ className, children, ...props }) {
65-
return <code {...props} className={clsx(className, 'inline-code')}>{children}</code>
67+
const InlineCode: React.FC<{ className: string, [key: string]: any }> = (props) => {
68+
const { className, children, ...others } = props
69+
return <code {...others} className={clsx(className, 'inline-code')}>{children}</code>
6670
}
6771

6872
const myComponents = {
6973
details: Details,
7074
summary: Summary,
71-
a: LinkGetter(),
72-
inlineCode: InlineCode,
75+
a: LinkGetter,
7376
inlinecode: InlineCode,
74-
}
77+
} as ReactiveHastComponents
78+
79+
const isWIP = wordCount === 0 || (tags?.findIndex((x: string) => x === 'WIP') >= 0)
7580

76-
const isWIP = wordCount === 0 || (tags?.findIndex(x => x === 'WIP') >= 0)
7781
return (
7882
<StyledLayout
7983
location={location}
+47-57
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,106 @@
11
import React from 'react'
22
import { Helmet } from 'react-helmet'
33
import { useLocation } from '@reach/router'
4-
import { useStaticQuery, graphql } from 'gatsby'
4+
import { graphql, useStaticQuery } from 'gatsby'
5+
import { RequiredNonNull } from '../types/common'
6+
import { Article, WithContext } from 'schema-dts'
57

6-
interface Props {
8+
interface SEOProps {
79
title: string;
810
description: string;
9-
image: string;
1011
article: boolean;
1112
author: string;
1213
tags: string[];
1314
dateModified: string;
1415
datePublished: string;
16+
image?: string
1517
}
1618

17-
const SEO: React.FC<Props> = (props: Props) => {
19+
const SEO: React.FC<SEOProps> = (props: SEOProps) => {
20+
const { pathname } = useLocation()
21+
const { site: { siteMetadata } } = useStaticQuery<GatsbyTypes.SEOQuery>(graphql`
22+
query SEO {
23+
site {
24+
siteMetadata {
25+
defaultTitle: title
26+
defaultDescription: description
27+
siteUrl
28+
defaultAuthor: author
29+
}
30+
}
31+
}
32+
`) as RequiredNonNull<GatsbyTypes.SEOQuery>
33+
1834
const {
1935
title = null,
2036
description = null,
21-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
22-
image = null,
2337
article = false,
24-
author = null,
38+
author = '',
2539
tags = null,
2640
dateModified,
2741
datePublished,
2842
} = props
29-
const { pathname } = useLocation()
30-
const { site } = useStaticQuery<GatsbyTypes.SEOQuery>(query)
3143

32-
const {
33-
defaultTitle,
34-
defaultDescription,
35-
siteUrl,
36-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
37-
defaultAuthor,
38-
} = site.siteMetadata
3944

4045
const seo = {
41-
title: title || defaultTitle,
42-
description: description || defaultDescription,
43-
// image: `${siteUrl}${image}`,
46+
title: title || siteMetadata.defaultTitle,
47+
description: description || siteMetadata.defaultDescription,
4448
image: 'https://cdn.jsdelivr.net/npm/oicdn@0.0.2/wordArt.webp',
45-
url: `${siteUrl}${pathname}`,
49+
url: `${siteMetadata.siteUrl}${pathname}`,
4650
author: author && author.split(','),
4751
tags: tags,
4852
}
4953

50-
const schemaMarkUp = {
54+
const schemaMarkUp: WithContext<Article> = {
55+
'@context': 'https://schema.org',
56+
'@type': 'Article',
5157
headline: seo.title,
52-
image: ['https://cdn.jsdelivr.net/npm/oicdn@0.0.2/wordArt.webp'],
58+
image: [seo.image],
5359
datePublished: datePublished,
5460
dateModified: dateModified,
5561
mainEntityOfPage: seo.url,
5662
author: {
63+
'@type': 'Person',
5764
name: author,
5865
},
5966
publisher: {
67+
'@type': 'Organization',
6068
name: 'OI Wiki',
6169
logo: {
62-
url: 'https://cdn.jsdelivr.net/npm/oicdn@0.0.2/wordArt.webp',
70+
'@type': 'ImageObject',
71+
url: seo.image,
6372
},
6473
},
6574
}
66-
schemaMarkUp['@context'] = 'https://schema.org'
67-
schemaMarkUp['@type'] = 'Article'
68-
schemaMarkUp.author['@type'] = 'Person'
69-
schemaMarkUp.publisher['@type'] = 'Organization'
70-
schemaMarkUp.publisher.logo['@type'] = 'ImageObject'
75+
7176

7277
return (
73-
<Helmet >
74-
<meta name="description" content={seo.description} />
75-
<meta name="image" content={seo.image} />
78+
<Helmet>
79+
<meta name="description" content={seo.description}/>
80+
<meta name="image" content={seo.image}/>
7681

77-
{seo.url && <meta property="og:url" content={seo.url} />}
82+
{seo.url && <meta property="og:url" content={seo.url}/>}
7883

79-
{article && <meta property="og:type" content="article" />}
80-
{seo.tags && seo.tags.map((tag) => <meta key={tag} property="og:article:tag" content={tag} />)}
81-
{seo.author && seo.author.map((author) => <meta key={author} property="og:article:author" content={author} />)}
84+
{article && <meta property="og:type" content="article"/>}
85+
{seo.tags && seo.tags.map((tag) => <meta key={tag} property="og:article:tag" content={tag}/>)}
86+
{seo.author && seo.author.map((author) => <meta key={author} property="og:article:author" content={author}/>)}
8287

83-
{seo.title && <meta property="og:title" content={seo.title} />}
88+
{seo.title && <meta property="og:title" content={seo.title}/>}
8489

85-
{seo.description && <meta property="og:description" content={seo.description} />}
90+
{seo.description && <meta property="og:description" content={seo.description}/>}
8691

87-
{seo.image && <meta property="og:image" content={seo.image} />}
92+
{seo.image && <meta property="og:image" content={seo.image}/>}
8893

89-
<meta name="twitter:card" content="summary_large_image" />
94+
<meta name="twitter:card" content="summary_large_image"/>
9095

91-
{seo.title && <meta name="twitter:title" content={seo.title} />}
96+
{seo.title && <meta name="twitter:title" content={seo.title}/>}
9297

93-
{seo.description && (
94-
<meta name="twitter:description" content={seo.description} />
95-
)}
98+
{seo.description && <meta name="twitter:description" content={seo.description}/>}
9699

97-
{seo.image && <meta name="twitter:image" content={seo.image} />}
100+
{seo.image && <meta name="twitter:image" content={seo.image}/>}
98101
{schemaMarkUp && <script type="application/ld+json">{JSON.stringify(schemaMarkUp, null, 2)}</script>}
99102
</Helmet>
100103
)
101104
}
102105

103106
export default SEO
104-
105-
const query = graphql`
106-
query SEO {
107-
site {
108-
siteMetadata {
109-
defaultTitle: title
110-
defaultDescription: description
111-
siteUrl
112-
defaultAuthor: author
113-
}
114-
}
115-
}
116-
`

gatsby-theme-oi-wiki/src/lib/MDRenderer.js

-8
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react'
2+
import reactiveHast, { ReactiveHastComponents, ReactiveHastHtmlAst } from './reactiveHast'
3+
4+
export interface MDRendererProps {
5+
components: ReactiveHastComponents;
6+
htmlAst: ReactiveHastHtmlAst;
7+
}
8+
9+
const MDRenderer: React.FC<MDRendererProps> = (props) => {
10+
const { components, htmlAst } = props
11+
return reactiveHast({
12+
...htmlAst,
13+
tagName: 'div',
14+
}, components ?? {}) as ReturnType<React.FC>
15+
}
16+
17+
export default React.memo(MDRenderer, () => true)

0 commit comments

Comments
 (0)