Update/fix some web stuff. (#1429)
* Update/fix some web stuff. Also added lefthook with some linting config. * Add note about lefthook. * Enable sort imports eslint rule. * This statement is untrue * Remove cypress video, add to gitignore * Add web CI action * Set the right dir here * Try this
This commit is contained in:
parent
1296ab8517
commit
bd5b7c87fa
|
@ -0,0 +1,27 @@
|
||||||
|
name: Web CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Use Node.js 18
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
cache: npm
|
||||||
|
cache-dependency-path: '**/package-lock.json'
|
||||||
|
- run: npm ci
|
||||||
|
working-directory: web
|
||||||
|
- run: npm run lint
|
||||||
|
working-directory: web
|
||||||
|
- run: npm run build --if-present
|
||||||
|
working-directory: web
|
||||||
|
- run: npm run e2e:headless
|
||||||
|
working-directory: web
|
|
@ -4,4 +4,4 @@ module.exports = {
|
||||||
singleQuote: true,
|
singleQuote: true,
|
||||||
tabWidth: 2,
|
tabWidth: 2,
|
||||||
useTabs: false,
|
useTabs: false,
|
||||||
};
|
}
|
|
@ -22,7 +22,16 @@ _Patches submitted in issues, email, or elsewhere may be ignored._
|
||||||
|
|
||||||
## Coding Style
|
## Coding Style
|
||||||
|
|
||||||
Code should be formatted using `clang-format`. By configuring Conky with `cmake -DCHECK_CODE_QUALITY=ON`, you will be able to run `make clang-format` to automatically format code. If code in your PR is not formatted according to [`.clang-format`](.clang-format), the checks will not pass.
|
Code should be formatted using `clang-format`. By configuring Conky with `cmake -DCHECK_CODE_QUALITY=ON`, you will be able to run `make clang-format` to automatically format code.
|
||||||
|
|
||||||
|
## Git hooks
|
||||||
|
|
||||||
|
To make life easier, you can use
|
||||||
|
[lefthook](https://github.com/evilmartians/lefthook) to handle some basic
|
||||||
|
linting with a pre-commit hook, as defined in [lefthook.yml](lefthook.yml).
|
||||||
|
Follow the [installation guide for
|
||||||
|
lefhook](https://github.com/evilmartians/lefthook/blob/master/docs/install.md),
|
||||||
|
then run `lefthook install` to enable the hooks.
|
||||||
|
|
||||||
## Unit Testing
|
## Unit Testing
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
pre-commit:
|
||||||
|
commands:
|
||||||
|
web-linter:
|
||||||
|
parallel: true
|
||||||
|
run: |
|
||||||
|
npx eslint --fix {staged_files} \
|
||||||
|
&& git add {staged_files}
|
||||||
|
root: web/
|
||||||
|
glob: '*.{ts,tsx,js,jsx}'
|
||||||
|
cpp-linter:
|
||||||
|
run: |
|
||||||
|
clang-format -i {staged_files} \
|
||||||
|
&& git add {staged_files}
|
||||||
|
glob: '*.{c,cc,cxx,h,cpp}'
|
||||||
|
misc-linter:
|
||||||
|
run: |
|
||||||
|
npx prettier --write {staged_files} \
|
||||||
|
&& git add {staged_files}
|
||||||
|
glob: '*.{md,json,yml,yaml}'
|
|
@ -1,7 +1,16 @@
|
||||||
{
|
{
|
||||||
"extends": ["next/core-web-vitals", "prettier"],
|
"extends": [
|
||||||
"settings": {
|
"eslint:recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"next/core-web-vitals",
|
||||||
|
"prettier"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"plugins": ["@typescript-eslint"],
|
||||||
|
"root": true,
|
||||||
|
"settings": {
|
||||||
"mdx/code-blocks": true,
|
"mdx/code-blocks": true,
|
||||||
"mdx/language-mapper": {}
|
"mdx/language-mapper": {},
|
||||||
|
"sort-imports": "error"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,3 +39,6 @@ yarn-error.log*
|
||||||
|
|
||||||
# IDEs
|
# IDEs
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
# Cypress videos
|
||||||
|
cypress/videos
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
import Link from 'next/link'
|
|
||||||
import { Url } from 'url'
|
|
||||||
|
|
||||||
interface CustomLinkProps {
|
|
||||||
as: Url
|
|
||||||
href: Url
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function CustomLink({
|
|
||||||
as,
|
|
||||||
href,
|
|
||||||
...otherProps
|
|
||||||
}: CustomLinkProps) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Link as={as} href={href}>
|
|
||||||
<a {...otherProps} />
|
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -32,9 +32,7 @@ export default function Docs({ docs, braces, assign }: DocsProps) {
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="px-2 py-3">
|
<div className="px-2 py-3">
|
||||||
<Link href={`#${doc.name}`}>
|
<Link href={`#${doc.name}`}>
|
||||||
<a>
|
<LinkIcon size={20} />
|
||||||
<LinkIcon size={20} />
|
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-col p-1">
|
<div className="flex-col p-1">
|
||||||
|
|
|
@ -13,7 +13,8 @@ type HeaderProps = {
|
||||||
|
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import Search from './Search'
|
import Search from './Search'
|
||||||
import { SearchIndex } from '../utils/search'
|
import { SearchIndex, SearchItem } from '../utils/search'
|
||||||
|
import Fuse from 'fuse.js'
|
||||||
|
|
||||||
interface NavLinkProps {
|
interface NavLinkProps {
|
||||||
href: string
|
href: string
|
||||||
|
@ -26,12 +27,11 @@ const NavLink: React.FunctionComponent<NavLinkProps> = (props) => {
|
||||||
? 'bg-rose-100 dark:bg-rose-900'
|
? 'bg-rose-100 dark:bg-rose-900'
|
||||||
: ''
|
: ''
|
||||||
return (
|
return (
|
||||||
<Link href={props.href}>
|
<Link
|
||||||
<a
|
href={props.href}
|
||||||
className={`m-0.5 p-1 self-end hover:ring-1 ring-black dark:ring-white hover:bg-rose-300 dark:hover:bg-rose-700 ${bg} rounded`}
|
className={`m-0.5 p-1 self-end hover:ring-1 ring-black dark:ring-white hover:bg-rose-300 dark:hover:bg-rose-700 ${bg} rounded`}
|
||||||
>
|
>
|
||||||
{props.name}
|
{props.name}
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -43,14 +43,21 @@ export default function Header({
|
||||||
searchIndex,
|
searchIndex,
|
||||||
}: HeaderProps) {
|
}: HeaderProps) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const fuse = React.useMemo(() => {
|
||||||
|
const options: Fuse.IFuseOptions<SearchItem> = {}
|
||||||
|
return new Fuse(
|
||||||
|
searchIndex.list,
|
||||||
|
options,
|
||||||
|
Fuse.parseIndex(searchIndex.index)
|
||||||
|
)
|
||||||
|
}, [searchIndex])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border-b-1 backdrop-blur-lg bg-white dark:bg-black bg-opacity-20 dark:bg-opacity-20 transition">
|
<div className="border-b-1 backdrop-blur-lg bg-white dark:bg-black bg-opacity-20 dark:bg-opacity-20 transition">
|
||||||
<header className="max-w-3xl mx-auto m-0 p-1 grow flex w-full">
|
<header className="max-w-3xl mx-auto m-0 p-1 grow flex w-full">
|
||||||
<h1 className="px-2 text-3xl dark:text-white self-end">
|
<h1 className="px-2 text-3xl dark:text-white self-end">
|
||||||
<Link href="/">
|
<Link href="/">
|
||||||
<a>
|
<strong>{name}</strong>
|
||||||
<strong>{name}</strong>
|
|
||||||
</a>
|
|
||||||
</Link>
|
</Link>
|
||||||
</h1>
|
</h1>
|
||||||
{router.asPath != '/' && (
|
{router.asPath != '/' && (
|
||||||
|
@ -61,7 +68,7 @@ export default function Header({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<LineChart width={380} height={40} darkMode={darkMode} />
|
<LineChart width={380} height={40} darkMode={darkMode} />
|
||||||
<Search index={searchIndex} />
|
<Search fuse={fuse} />
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="border-r mx-1 px-1 border-slate-700">
|
<div className="border-r mx-1 px-1 border-slate-700">
|
||||||
<a href="https://github.com/brndnmtthws/conky">
|
<a href="https://github.com/brndnmtthws/conky">
|
||||||
|
|
|
@ -34,7 +34,7 @@ export default function Layout({ children, searchIndex }: LayoutProps) {
|
||||||
}, [darkMode])
|
}, [darkMode])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
var darkQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
const darkQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
||||||
|
|
||||||
darkQuery.onchange = (e) => {
|
darkQuery.onchange = (e) => {
|
||||||
if (e.matches) {
|
if (e.matches) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
|
import { useEffect, useMemo, useRef } from 'react'
|
||||||
import * as d3 from 'd3'
|
import * as d3 from 'd3'
|
||||||
import { random } from 'colord'
|
import { random } from 'colord'
|
||||||
|
|
||||||
|
@ -40,12 +40,12 @@ function fetchData() {
|
||||||
const data = JSON.parse(storedData)
|
const data = JSON.parse(storedData)
|
||||||
return data || []
|
return data || []
|
||||||
}
|
}
|
||||||
var data = fetchData()
|
const data = fetchData()
|
||||||
|
|
||||||
export const LineChart = ({ width, height, darkMode }: LineChartProps) => {
|
export const LineChart = ({ width, height, darkMode }: LineChartProps) => {
|
||||||
const timerRef = useRef<NodeJS.Timeout>()
|
const timerRef = useRef<NodeJS.Timeout>()
|
||||||
const svgRef = useRef(null)
|
const svgRef = useRef(null)
|
||||||
const [stroke, setStroke] = useState(random())
|
const stroke = useMemo(() => random(), [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const doIt = (data: DataPoint[]) => {
|
const doIt = (data: DataPoint[]) => {
|
||||||
|
@ -59,7 +59,7 @@ export const LineChart = ({ width, height, darkMode }: LineChartProps) => {
|
||||||
.range([height, 0])
|
.range([height, 0])
|
||||||
|
|
||||||
// X axis
|
// X axis
|
||||||
const [xMin, xMax] = d3.extent(data, (d) => d.x)
|
const [, xMax] = d3.extent(data, (d) => d.x)
|
||||||
const xScale = d3
|
const xScale = d3
|
||||||
.scaleLinear()
|
.scaleLinear()
|
||||||
.domain([(xMax || 0) - width, xMax || 0])
|
.domain([(xMax || 0) - width, xMax || 0])
|
||||||
|
@ -83,7 +83,7 @@ export const LineChart = ({ width, height, darkMode }: LineChartProps) => {
|
||||||
.attr('x', (d) => xScale(d.x))
|
.attr('x', (d) => xScale(d.x))
|
||||||
.attr('y', (d) => yScale(d.y))
|
.attr('y', (d) => yScale(d.y))
|
||||||
.attr('height', (d) => yScale((max || 0) - d.y))
|
.attr('height', (d) => yScale((max || 0) - d.y))
|
||||||
.attr('width', (d) => 1),
|
.attr('width', () => 1),
|
||||||
(update) =>
|
(update) =>
|
||||||
update
|
update
|
||||||
.transition()
|
.transition()
|
||||||
|
@ -95,7 +95,7 @@ export const LineChart = ({ width, height, darkMode }: LineChartProps) => {
|
||||||
.attr('x', (d) => xScale(d.x))
|
.attr('x', (d) => xScale(d.x))
|
||||||
.attr('y', (d) => yScale(d.y))
|
.attr('y', (d) => yScale(d.y))
|
||||||
.attr('height', (d) => yScale((max || 0) - d.y))
|
.attr('height', (d) => yScale((max || 0) - d.y))
|
||||||
.attr('width', (d) => 1),
|
.attr('width', () => 1),
|
||||||
(exit) => exit.call((d) => d.transition().remove())
|
(exit) => exit.call((d) => d.transition().remove())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import Fuse from 'fuse.js'
|
import Fuse from 'fuse.js'
|
||||||
import React, { Fragment, useCallback, useEffect, useState } from 'react'
|
import React, { Fragment, useCallback, useEffect, useState } from 'react'
|
||||||
import { Search as SearchIcon } from 'react-feather'
|
import { Search as SearchIcon } from 'react-feather'
|
||||||
import { SearchIndex, SearchItem } from '../utils/search'
|
import { SearchItem } from '../utils/search'
|
||||||
import { Dialog, Transition, Combobox } from '@headlessui/react'
|
import { Dialog, Transition, Combobox } from '@headlessui/react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
export interface SearchProps {
|
export interface SearchProps {
|
||||||
index: SearchIndex
|
fuse: Fuse<SearchItem>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SearchResultProps {
|
interface SearchResultProps {
|
||||||
|
@ -57,23 +57,13 @@ const SearchResult: React.FunctionComponent<SearchResultProps> = (props) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Search: React.FunctionComponent<SearchProps> = (props) => {
|
const Search: React.FunctionComponent<SearchProps> = ({ fuse }) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [searchText, setSearchText] = useState('')
|
const [searchText, setSearchText] = useState('')
|
||||||
const [selected, setSelected] = useState<
|
|
||||||
Fuse.FuseResult<SearchItem> | undefined
|
|
||||||
>(undefined)
|
|
||||||
const [searchResults, setSearchResults] = useState<
|
const [searchResults, setSearchResults] = useState<
|
||||||
Fuse.FuseResult<SearchItem>[]
|
Fuse.FuseResult<SearchItem>[]
|
||||||
>([])
|
>([])
|
||||||
const [fuse, setFuse] = useState(() => {
|
|
||||||
const options: Fuse.IFuseOptions<SearchItem> = {}
|
|
||||||
return new Fuse(
|
|
||||||
props.index.list,
|
|
||||||
options,
|
|
||||||
Fuse.parseIndex(props.index.index)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
const [isOpen, setIsOpen] = useState(false)
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
const handleKeyPress = useCallback(
|
const handleKeyPress = useCallback(
|
||||||
(event: KeyboardEvent) => {
|
(event: KeyboardEvent) => {
|
||||||
|
@ -159,7 +149,7 @@ const Search: React.FunctionComponent<SearchProps> = (props) => {
|
||||||
<div className="fixed inset-0">
|
<div className="fixed inset-0">
|
||||||
<div className="flex h-screen w-screen items-start justify-center p-16 text-center">
|
<div className="flex h-screen w-screen items-start justify-center p-16 text-center">
|
||||||
<Dialog.Panel className="flex flex-col max-h-full w-full max-w-2xl p-1 bg-gray-200 dark:bg-gray-800 transform rounded-xl text-left align-middle shadow transition-all border border-gray-800 dark:border-white border-opacity-10 dark:border-opacity-10">
|
<Dialog.Panel className="flex flex-col max-h-full w-full max-w-2xl p-1 bg-gray-200 dark:bg-gray-800 transform rounded-xl text-left align-middle shadow transition-all border border-gray-800 dark:border-white border-opacity-10 dark:border-opacity-10">
|
||||||
<Combobox value={selected} nullable onChange={onChange}>
|
<Combobox nullable onChange={onChange}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<Combobox.Label className="flex items-center ml-2">
|
<Combobox.Label className="flex items-center ml-2">
|
||||||
<SearchIcon size={32} />
|
<SearchIcon size={32} />
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { Dispatch, SetStateAction } from 'react'
|
|
||||||
|
|
||||||
const sunIcon = (
|
const sunIcon = (
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -11,18 +11,20 @@
|
||||||
"url": "https://github.com/brndnmtthws/conky/issues"
|
"url": "https://github.com/brndnmtthws/conky/issues"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next",
|
"dev": "next dev",
|
||||||
"dev:watch": "next-remote-watch ./documents",
|
"dev:watch": "next-remote-watch ./documents",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"export": "next build && next export",
|
"export": "next build && next export",
|
||||||
"lint": "next lint"
|
"lint": "next lint",
|
||||||
|
"e2e": "start-server-and-test dev http://localhost:3000 \"cypress open --e2e\"",
|
||||||
|
"e2e:headless": "start-server-and-test dev http://localhost:3000 \"cypress run --e2e\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/fira-code": "^4.5.13",
|
"@fontsource/fira-code": "^4.5.13",
|
||||||
"@fontsource/inter": "^4.5.15",
|
"@fontsource/inter": "^4.5.15",
|
||||||
"@fontsource/newsreader": "^4.5.10",
|
"@fontsource/newsreader": "^4.5.10",
|
||||||
"@headlessui/react": "^1.7.11",
|
"@headlessui/react": "^1.7.12",
|
||||||
"@mapbox/rehype-prism": "^0.8.0",
|
"@mapbox/rehype-prism": "^0.8.0",
|
||||||
"@netlify/plugin-nextjs": "^4.30.4",
|
"@netlify/plugin-nextjs": "^4.30.4",
|
||||||
"@tailwindcss/typography": "^0.5.9",
|
"@tailwindcss/typography": "^0.5.9",
|
||||||
|
@ -32,7 +34,7 @@
|
||||||
"fuse.js": "^6.6.2",
|
"fuse.js": "^6.6.2",
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"inter-ui": "^3.19.3",
|
"inter-ui": "^3.19.3",
|
||||||
"next": "^13.1.6",
|
"next": "^13.2.1",
|
||||||
"prismjs": "^1.29.0",
|
"prismjs": "^1.29.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
@ -41,23 +43,25 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/d3": "^7.4.0",
|
"@types/d3": "^7.4.0",
|
||||||
"@types/mapbox__rehype-prism": "^0.8.0",
|
"@types/mapbox__rehype-prism": "^0.8.0",
|
||||||
"@types/node": "^18.14.0",
|
"@types/node": "^18.14.1",
|
||||||
"@types/react": "^18.0.28",
|
"@types/react": "^18.0.28",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.53.0",
|
||||||
|
"@typescript-eslint/parser": "^5.53.0",
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
"cypress": "^12.6.0",
|
"cypress": "^12.7.0",
|
||||||
"eslint": "^8.34.0",
|
"eslint": "^8.34.0",
|
||||||
"eslint-config-next": "^13.1.6",
|
"eslint-config-next": "^13.2.1",
|
||||||
"eslint-config-prettier": "^8.6.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-mdx": "^2.0.5",
|
"eslint-plugin-mdx": "^2.0.5",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"netlify-plugin-cypress": "^2.2.0",
|
"netlify-plugin-cypress": "^2.2.1",
|
||||||
"next-mdx-remote": "^4.3.0",
|
"next-mdx-remote": "^4.3.0",
|
||||||
"next-remote-watch": "2.0.0",
|
"next-remote-watch": "2.0.0",
|
||||||
"postcss": "^8.4.21",
|
"postcss": "^8.4.21",
|
||||||
"rehype-stringify": "^9.0.3",
|
"rehype-stringify": "^9.0.3",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
|
"start-server-and-test": "^1.15.4",
|
||||||
"tailwindcss": "^3.2.7",
|
"tailwindcss": "^3.2.7",
|
||||||
"tslint": "^6.1.3",
|
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,18 +7,19 @@ import {
|
||||||
|
|
||||||
import { MDXRemote, MDXRemoteProps } from 'next-mdx-remote'
|
import { MDXRemote, MDXRemoteProps } from 'next-mdx-remote'
|
||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import CustomLink from '../../components/CustomLink'
|
|
||||||
import Layout from '../../components/Layout'
|
import Layout from '../../components/Layout'
|
||||||
import SEO from '../../components/SEO'
|
import SEO from '../../components/SEO'
|
||||||
import { GetStaticProps } from 'next'
|
import { GetStaticProps } from 'next'
|
||||||
import { getSearchIndex, SearchIndex } from '../../utils/search'
|
import { getSearchIndex, SearchIndex } from '../../utils/search'
|
||||||
|
import Link from 'next/link'
|
||||||
|
import { MDXComponents } from 'mdx/types'
|
||||||
|
|
||||||
// Custom components/renderers to pass to MDX.
|
// Custom components/renderers to pass to MDX.
|
||||||
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
// Since the MDX files aren't loaded by webpack, they have no knowledge of how
|
||||||
// to handle import statements. Instead, you must include components in scope
|
// to handle import statements. Instead, you must include components in scope
|
||||||
// here.
|
// here.
|
||||||
const components = {
|
const components = {
|
||||||
a: CustomLink,
|
a: Link,
|
||||||
// It also works with dynamically-imported components, which is especially
|
// It also works with dynamically-imported components, which is especially
|
||||||
// useful for conditionally loading components for certain routes.
|
// useful for conditionally loading components for certain routes.
|
||||||
// See the notes in README.md for more details.
|
// See the notes in README.md for more details.
|
||||||
|
@ -58,7 +59,7 @@ export default function DocumentPage({
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<article className="prose dark:prose-invert prose-lg lg:prose-xl">
|
<article className="prose dark:prose-invert prose-lg lg:prose-xl">
|
||||||
<MDXRemote {...source} components={components as any} />
|
<MDXRemote {...source} components={components as MDXComponents} />
|
||||||
</article>
|
</article>
|
||||||
</main>
|
</main>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import Layout from '../components/Layout'
|
||||||
import ArrowIcon from '../components/ArrowIcon'
|
import ArrowIcon from '../components/ArrowIcon'
|
||||||
import SEO from '../components/SEO'
|
import SEO from '../components/SEO'
|
||||||
import { getSearchIndex, SearchIndex } from '../utils/search'
|
import { getSearchIndex, SearchIndex } from '../utils/search'
|
||||||
import { Url } from 'url'
|
|
||||||
|
|
||||||
const pages = [
|
const pages = [
|
||||||
{
|
{
|
||||||
|
@ -34,14 +33,14 @@ interface IndexItemProps {
|
||||||
const IndexItem: React.FunctionComponent<IndexItemProps> = (props) => {
|
const IndexItem: React.FunctionComponent<IndexItemProps> = (props) => {
|
||||||
return (
|
return (
|
||||||
<div className="md:first:rounded-t-lg md:last:rounded-b-lg backdrop-blur-lg bg-slate-300 dark:bg-black dark:bg-opacity-30 bg-opacity-10 hover:bg-opacity-30 dark:hover:bg-opacity-50 transition border border-gray-800 dark:border-white border-opacity-10 dark:border-opacity-10 border-b-0 last:border-b hover:border-b hovered-sibling:border-t-0">
|
<div className="md:first:rounded-t-lg md:last:rounded-b-lg backdrop-blur-lg bg-slate-300 dark:bg-black dark:bg-opacity-30 bg-opacity-10 hover:bg-opacity-30 dark:hover:bg-opacity-50 transition border border-gray-800 dark:border-white border-opacity-10 dark:border-opacity-10 border-b-0 last:border-b hover:border-b hovered-sibling:border-t-0">
|
||||||
<Link as={props.as} href={props.href}>
|
<Link
|
||||||
<a className="py-2 lg:py-4 px-2 lg:px-4 block focus:outline-none focus:ring-4">
|
as={props.as}
|
||||||
<h2 className="text-xl md:text-2xl">{props.title}</h2>
|
href={props.href}
|
||||||
{props.desc && (
|
className="py-2 lg:py-4 px-2 lg:px-4 block focus:outline-none focus:ring-4"
|
||||||
<p className="mt-3 text-lg opacity-60">{props.desc}</p>
|
>
|
||||||
)}
|
<h2 className="text-xl md:text-2xl">{props.title}</h2>
|
||||||
<ArrowIcon className="mt-4" />
|
{props.desc && <p className="mt-3 text-lg opacity-60">{props.desc}</p>}
|
||||||
</a>
|
<ArrowIcon className="mt-4" />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,4 +5,4 @@ module.exports = {
|
||||||
tailwindcss: {},
|
tailwindcss: {},
|
||||||
autoprefixer: {},
|
autoprefixer: {},
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"lib": [
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"dom",
|
|
||||||
"dom.iterable",
|
|
||||||
"esnext"
|
|
||||||
],
|
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
|
@ -19,12 +15,6 @@
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve"
|
"jsx": "preserve"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
"next-env.d.ts",
|
"exclude": ["node_modules"]
|
||||||
"**/*.ts",
|
|
||||||
"**/*.tsx"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue