Skip to content

Commit

Permalink
refactor: add types to doc.js & relative files
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyeYoung committed Jul 27, 2021
1 parent c990c6f commit 1068f5b
Show file tree
Hide file tree
Showing 12 changed files with 359 additions and 329 deletions.
3 changes: 3 additions & 0 deletions gatsby-theme-oi-wiki/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
"use-persisted-state": "^0.3.0"
},
"devDependencies": {
"@types/mark.js": "^8.11.6",
"@types/react-helmet": "^6.1.1",
"@types/use-persisted-state": "^0.3.0",
"@typescript-eslint/eslint-plugin": "^4.28.3",
"@typescript-eslint/parser": "^4.28.3",
"eslint": "^7.29.0",
Expand All @@ -69,6 +71,7 @@
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.1.2",
"gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.24",
"schema-dts": "^0.9.0",
"ts-graphql-plugin": "^2.1.3",
"typescript": "^4.3.5"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
import MDRenderer from '../lib/MDRenderer'
import React, { useEffect } from 'react'
import React, { useCallback, useEffect } from 'react'
import Mark from 'mark.js'
import Details from './Details.tsx'
import Summary from './Summary.tsx'
import { SmartLink } from './Link'
import SEO from './Seo'
import clsx from 'clsx'

import MDRenderer from '../lib/MDRenderer'
import Details from './Details'
import Summary from './Summary'
import { SmartLink, SmartLinkProps } from './Link'
import SEO from './Seo'
import StyledLayout from './StyledLayout'
import { DeepRequiredNonNull, DeepWriteable, Nullable } from '../types/common'
import { ReactiveHastComponents } from '../lib/reactiveHast'

export interface MdxProps {
data: DeepWriteable<DeepRequiredNonNull<GatsbyTypes.DocQuery>>
location: Location & { state: Nullable<{ searchKey: string }> };
}

function Mdx ({ data: { mdx }, location }) {
// console.log(mdx);
// const headingTitle = mdx.headings[0] && mdx.headings[0].value
const title = mdx.slug === '/' ? null : mdx.frontmatter.title
const Mdx: React.FC<MdxProps> = ({ data: { mdx }, location }) => {
const title = mdx.fields.slug === '/' ? '' : mdx.frontmatter.title
const description = mdx.frontmatter.description || mdx.excerpt
const authors = mdx.frontmatter.author || null
const tags = mdx.frontmatter.tags || null
const noMeta = mdx.frontmatter.noMeta === 'true' || false
const noComment = mdx.frontmatter.noComment === 'true' || false
const noEdit = mdx.frontmatter.noEdit === 'true' || false
const authors = mdx.frontmatter.author || ''
const tags = mdx.frontmatter.tags || []
const noMeta = mdx.frontmatter.noMeta || false
const noComment = mdx.frontmatter.noComment || false
const noEdit = false
const toc = mdx.toc || null
const relativePath = mdx.parent.relativePath || ''
const modifiedTime = mdx.parent.modifiedTime || ''
Expand All @@ -26,21 +32,21 @@ function Mdx ({ data: { mdx }, location }) {
const dateModified = mdx.parent.changeTime || ''
const isIndex = mdx.fields.isIndex

const highlightNode = (tagName, isHighlight) => {
const mainNodes = document.getElementsByTagName('main')
const nodes = mainNodes[0].getElementsByTagName(tagName)
const children = [...nodes]
children.forEach((node) => {
const instance = new Mark(node)
const highlightNode = useCallback((tagName: string, isHighlight: boolean): void => {
if (location.state?.searchKey) {
const mainNodes = document.getElementsByTagName('main')
const nodes = mainNodes[0].querySelectorAll(tagName)
const instance = new Mark(nodes)
instance[isHighlight ? 'mark' : 'unmark'](
location.state.searchKey,
{
exclude: ['span'],
})
})
}
}
}, [location.state?.searchKey])

useEffect(() => {
if (location?.state?.searchKey) {
if (location.state?.searchKey) {
highlightNode('h1', true)
highlightNode('h2', true)
highlightNode('h3', true)
Expand All @@ -53,27 +59,25 @@ function Mdx ({ data: { mdx }, location }) {
highlightNode('p', false)
}, 5000)
}
}, [])
}, [highlightNode, location.state?.searchKey])

function LinkGetter () {
return function TooltipLink (props) {
return <SmartLink {...props} pathname={location.pathname} isIndex={isIndex} tooltip={true}/>
}
}
const LinkGetter: React.FC<SmartLinkProps> = (props) =>
<SmartLink {...props} pathname={location.pathname} isIndex={isIndex} tooltip={true}/>

function InlineCode ({ className, children, ...props }) {
return <code {...props} className={clsx(className, 'inline-code')}>{children}</code>
const InlineCode: React.FC<{ className: string, [key: string]: any }> = (props) => {
const { className, children, ...others } = props
return <code {...others} className={clsx(className, 'inline-code')}>{children}</code>
}

const myComponents = {
details: Details,
summary: Summary,
a: LinkGetter(),
inlineCode: InlineCode,
a: LinkGetter,
inlinecode: InlineCode,
}
} as ReactiveHastComponents

const isWIP = wordCount === 0 || (tags?.findIndex((x: string) => x === 'WIP') >= 0)

const isWIP = wordCount === 0 || (tags?.findIndex(x => x === 'WIP') >= 0)
return (
<StyledLayout
location={location}
Expand Down
104 changes: 47 additions & 57 deletions gatsby-theme-oi-wiki/src/components/Seo.tsx
Original file line number Diff line number Diff line change
@@ -1,116 +1,106 @@
import React from 'react'
import { Helmet } from 'react-helmet'
import { useLocation } from '@reach/router'
import { useStaticQuery, graphql } from 'gatsby'
import { graphql, useStaticQuery } from 'gatsby'
import { RequiredNonNull } from '../types/common'
import { Article, WithContext } from 'schema-dts'

interface Props {
interface SEOProps {
title: string;
description: string;
image: string;
article: boolean;
author: string;
tags: string[];
dateModified: string;
datePublished: string;
image?: string
}

const SEO: React.FC<Props> = (props: Props) => {
const SEO: React.FC<SEOProps> = (props: SEOProps) => {
const { pathname } = useLocation()
const { site: { siteMetadata } } = useStaticQuery<GatsbyTypes.SEOQuery>(graphql`
query SEO {
site {
siteMetadata {
defaultTitle: title
defaultDescription: description
siteUrl
defaultAuthor: author
}
}
}
`) as RequiredNonNull<GatsbyTypes.SEOQuery>

const {
title = null,
description = null,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
image = null,
article = false,
author = null,
author = '',
tags = null,
dateModified,
datePublished,
} = props
const { pathname } = useLocation()
const { site } = useStaticQuery<GatsbyTypes.SEOQuery>(query)

const {
defaultTitle,
defaultDescription,
siteUrl,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
defaultAuthor,
} = site.siteMetadata

const seo = {
title: title || defaultTitle,
description: description || defaultDescription,
// image: `${siteUrl}${image}`,
title: title || siteMetadata.defaultTitle,
description: description || siteMetadata.defaultDescription,
image: 'https://cdn.jsdelivr.net/npm/[email protected]/wordArt.webp',
url: `${siteUrl}${pathname}`,
url: `${siteMetadata.siteUrl}${pathname}`,
author: author && author.split(','),
tags: tags,
}

const schemaMarkUp = {
const schemaMarkUp: WithContext<Article> = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: seo.title,
image: ['https://cdn.jsdelivr.net/npm/[email protected]/wordArt.webp'],
image: [seo.image],
datePublished: datePublished,
dateModified: dateModified,
mainEntityOfPage: seo.url,
author: {
'@type': 'Person',
name: author,
},
publisher: {
'@type': 'Organization',
name: 'OI Wiki',
logo: {
url: 'https://cdn.jsdelivr.net/npm/[email protected]/wordArt.webp',
'@type': 'ImageObject',
url: seo.image,
},
},
}
schemaMarkUp['@context'] = 'https://schema.org'
schemaMarkUp['@type'] = 'Article'
schemaMarkUp.author['@type'] = 'Person'
schemaMarkUp.publisher['@type'] = 'Organization'
schemaMarkUp.publisher.logo['@type'] = 'ImageObject'


return (
<Helmet >
<meta name="description" content={seo.description} />
<meta name="image" content={seo.image} />
<Helmet>
<meta name="description" content={seo.description}/>
<meta name="image" content={seo.image}/>

{seo.url && <meta property="og:url" content={seo.url} />}
{seo.url && <meta property="og:url" content={seo.url}/>}

{article && <meta property="og:type" content="article" />}
{seo.tags && seo.tags.map((tag) => <meta key={tag} property="og:article:tag" content={tag} />)}
{seo.author && seo.author.map((author) => <meta key={author} property="og:article:author" content={author} />)}
{article && <meta property="og:type" content="article"/>}
{seo.tags && seo.tags.map((tag) => <meta key={tag} property="og:article:tag" content={tag}/>)}
{seo.author && seo.author.map((author) => <meta key={author} property="og:article:author" content={author}/>)}

{seo.title && <meta property="og:title" content={seo.title} />}
{seo.title && <meta property="og:title" content={seo.title}/>}

{seo.description && <meta property="og:description" content={seo.description} />}
{seo.description && <meta property="og:description" content={seo.description}/>}

{seo.image && <meta property="og:image" content={seo.image} />}
{seo.image && <meta property="og:image" content={seo.image}/>}

<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:card" content="summary_large_image"/>

{seo.title && <meta name="twitter:title" content={seo.title} />}
{seo.title && <meta name="twitter:title" content={seo.title}/>}

{seo.description && (
<meta name="twitter:description" content={seo.description} />
)}
{seo.description && <meta name="twitter:description" content={seo.description}/>}

{seo.image && <meta name="twitter:image" content={seo.image} />}
{seo.image && <meta name="twitter:image" content={seo.image}/>}
{schemaMarkUp && <script type="application/ld+json">{JSON.stringify(schemaMarkUp, null, 2)}</script>}
</Helmet>
)
}

export default SEO

const query = graphql`
query SEO {
site {
siteMetadata {
defaultTitle: title
defaultDescription: description
siteUrl
defaultAuthor: author
}
}
}
`
8 changes: 0 additions & 8 deletions gatsby-theme-oi-wiki/src/lib/MDRenderer.js

This file was deleted.

17 changes: 17 additions & 0 deletions gatsby-theme-oi-wiki/src/lib/MDRenderer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react'
import reactiveHast, { ReactiveHastComponents, ReactiveHastHtmlAst } from './reactiveHast'

export interface MDRendererProps {
components: ReactiveHastComponents;
htmlAst: ReactiveHastHtmlAst;
}

const MDRenderer: React.FC<MDRendererProps> = (props) => {
const { components, htmlAst } = props
return reactiveHast({
...htmlAst,
tagName: 'div',
}, components ?? {}) as ReturnType<React.FC>
}

export default React.memo(MDRenderer, () => true)
Loading

0 comments on commit 1068f5b

Please sign in to comment.