diff --git a/components/MDXRoot.tsx b/components/MDXRoot.tsx index 84bb003..ea8bde4 100644 --- a/components/MDXRoot.tsx +++ b/components/MDXRoot.tsx @@ -1,4 +1,4 @@ -import MDXPageFactory from '@sup39/mdx-page'; +import {MDXPageFactory} from '@sup39/mdx-page'; import config from '#config'; export default MDXPageFactory(config); diff --git a/core/components/heading.tsx b/core/components/heading.tsx deleted file mode 100644 index b3cd81c..0000000 --- a/core/components/heading.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; - -const hx = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] as const; -export const anchoredHx = Object.fromEntries(hx.map(H => [ - H, - ({children, id, ...props}: React.ComponentProps<(typeof hx)[number]>) => ( - - {id && } - {children} - - ), -])); diff --git a/core/components/index.tsx b/core/components/index.tsx deleted file mode 100644 index 89caab1..0000000 --- a/core/components/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -export * from './heading'; -export * from './tag'; - -import {anchoredHx} from './heading'; -const mdx = {...anchoredHx}; -export default mdx; diff --git a/core/components/tag.tsx b/core/components/tag.tsx deleted file mode 100644 index 56ba441..0000000 --- a/core/components/tag.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from 'react'; - -export type TagFactory = { - [modifier: string]: TagFactory - (children: React.ReactNode): JSX.Element - (s: TemplateStringsArray, ...argv: any[]): JSX.Element -}; - -export type TagInfo = { - tagName: string - attrs: Record -}; -export const AttrProxyHandler: ProxyHandler = { - get({tagName, attrs}, modifier) { - let extra: TagInfo['attrs']; - if (typeof modifier === 'symbol') { - extra = {}; - } else if (modifier.startsWith('#')) { - // #id - extra = {id: modifier.slice(1)}; - } else if (modifier.includes('=')) { - // attr=value - const idx = modifier.indexOf('='); - extra = {[modifier.slice(0, idx)]: modifier.slice(idx+1)}; - } else { - // .class - extra = {class: attrs.class ? attrs.class+' '+modifier : modifier}; - } - // apply - return new Proxy( - Object.assign(()=>{}, {tagName, attrs: {...attrs, ...extra}}), - AttrProxyHandler, - ); - }, - apply({ - tagName, - attrs: {class: className, for: htmlFor, style, ...attrs}, - }, thisArg, args) { - const [s, ...argv] = args; - const children = s instanceof Array ? - s[0]+argv.map((e, i) => `${e}${s[i+1]}`).join('') : s; - return React.createElement( - tagName, - { - className, - htmlFor, - ...(style == null ? {} : { - style: Object.fromEntries(style.split(';').flatMap(line => { - const idx = line.indexOf(':'); - if (idx < 0) return []; - const key0 = line.slice(0, idx); - const value = line.slice(idx+1); - // kebab-case to camelCase - const ktoks = key0.split('-'); - const key = ktoks[0] + ktoks.slice(1).map(s => s[0].toUpperCase()+s.slice(1)).join(''); - return [[key, value]]; - })), - }), - ...attrs, - }, - children, - ); - }, -}; - -export const TagProxyHandler: ProxyHandler> = { - get(self, arg) { - const tagName = arg.toString(); - return new Proxy( - Object.assign(()=>{}, {tagName, attrs: {}}), - AttrProxyHandler, - ); - }, -}; - -export const T = new Proxy({}, TagProxyHandler); -export const S = T.span; -export const C = T.code; -export const tags = {T, S, C}; diff --git a/core/nav/Nav.tsx b/core/nav/Nav.tsx deleted file mode 100644 index d505bca..0000000 --- a/core/nav/Nav.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import {useState} from 'react'; -import type {NavEntryInfo} from './NavEntry'; -import {NavBase, HeadingInfo} from './NavBase'; -import {NavHeader, NavHeaderConfig} from './NavHeader'; - -export type NavConfig = { - site: NavHeaderConfig - nav: NavEntryInfo[] -} -export type NavProps = { - children?: React.ReactNode - headings: HeadingInfo[] - pathname: string - config: NavConfig -}; - -export function Nav({config, children, ...props}: NavProps) { - const [navFold, setNavFold] = useState(false); - return ( - - setNavFold(e=>!e)} /> - {children} - - ); -} diff --git a/core/nav/NavBase.tsx b/core/nav/NavBase.tsx deleted file mode 100644 index 8f2938a..0000000 --- a/core/nav/NavBase.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import {NavEntry, NavEntryInfo} from './NavEntry'; - -export type HeadingInfo = { - tagName: string; - label: string; - id: string; -}; -export type NavBaseProps = { - children?: React.ReactNode - headings: HeadingInfo[] - pathname: string - entries: NavEntryInfo[] - className?: string -} - -export function NavBase({ - children, headings, pathname, entries, className, -}: NavBaseProps) { - const headingsJSX = ; - - return ; -} diff --git a/core/nav/NavEntry.tsx b/core/nav/NavEntry.tsx deleted file mode 100644 index b4b1661..0000000 --- a/core/nav/NavEntry.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import {useState} from 'react'; -import Link from 'next/link'; -export type NavEntryInfo = { - label: string - link: string - children?: NavEntryInfo[] -}; - -export function NavEntry({ - entry: {label, link, children}, dir, here, children: childrenJSX, -}: {entry: NavEntryInfo, dir: string, here: string, children?: Body}) { - const href = dir+link; - const isHere = href.replace(/\/$/, '')===here; // remove trailing slash - const isRHere = isHere || here.startsWith(href); // here or is children - - const [toggle, setToggle] = useState(isRHere); - const entryCls = 'nav-entry'+(isHere ? ' nav-here' : ''); - return children?.length ?
<> -
- {label} - setToggle(e=>!e)}> -
- {isHere ? childrenJSX : <>} -
{ - children.map(entry => {childrenJSX}) - }
-
:
- {label} -
; -} diff --git a/core/nav/NavHeader.tsx b/core/nav/NavHeader.tsx deleted file mode 100644 index 82bb299..0000000 --- a/core/nav/NavHeader.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import Link from 'next/link'; - -export type NavHeaderConfig = { - title: string - subtitle?: string - icon?: string | { - href: string - alt?: string - size?: number - width?: number - height?: number - } -}; - -export function NavHeader({config, onToggleFold}: { - config: NavHeaderConfig - onToggleFold?: ()=>void -}) { - const {title, subtitle, icon: icon0} = config; - const icon = typeof icon0 === 'string' ? {href: icon0} : icon0; - return
- - {icon?.href && {icon?.alt} -
-
{title}
-
{subtitle}
-
- -
-
; -} diff --git a/core/nav/index.tsx b/core/nav/index.tsx deleted file mode 100644 index 3306a5a..0000000 --- a/core/nav/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export * from './Nav'; -export * from './NavBase'; -export * from './NavEntry'; -export * from './NavHeader'; - -import {Nav} from './Nav'; -export default Nav; diff --git a/core/page/Footer.tsx b/core/page/Footer.tsx deleted file mode 100644 index f4fc5c7..0000000 --- a/core/page/Footer.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -export type FooterConfig = { - site: { - startYear?: number - author: string - } -}; - -export function Footer({config}: {config: FooterConfig}) { - const year = new Date().getFullYear(); - const {site: {startYear: year0 = year, author}} = config; - const yearStr = year>year0 ? `${year0}-${year}` : year; - return ; -} diff --git a/core/page/MDXPage.tsx b/core/page/MDXPage.tsx deleted file mode 100644 index 0999568..0000000 --- a/core/page/MDXPage.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import Head from 'next/head'; -import {Nav, NavHeaderConfig} from '@sup39/mdx-nav'; -import {Footer} from './Footer'; -import {MetaInfo} from './MetaInfo'; -import {I18N, LocaleInfo, translate} from './i18n'; -import {I18NNavEntryInfo, translateNav} from './i18n-nav'; - -type HeadingInfo = { - tagName: string; - label: string; - id: string; -}; - -export type MDXProps = { - children: JSX.Element - router: {pathname: string} & LocaleInfo - meta: Partial<{ - title: I18N - description: I18N - h1: I18N - [key: string]: any - }> - headings: HeadingInfo[] - config: MDXConfig -}; - -export type MDXConfig = { - site: { - startYear?: number - author: string - title: I18N - subtitle?: I18N - } & Omit - metaFields?: {label: I18N, attr: string}[] - nav: I18NNavEntryInfo[] -} - -export function MDXPage({ - children, router, meta: meta18={}, headings, config, -}: MDXProps) { - const meta = Object.fromEntries(Object.entries(meta18).map(([k, v]) => [ - k, translate(v, router), - ])); - const {title, description} = meta; - const h1 = meta.h1 ?? title; - - const metaFields = config.metaFields?.map(({label, attr}) => ({ - label: translate(label, router), - attr, - })) ?? []; - - const {pathname} = router; - const navConfig = { - site: { - ...config.site, - title: translate(config.site.title, router), - subtitle: translate(config.site.subtitle, router), - }, - nav: translateNav(config.nav, router), - }; - - return <> - - {title && {title}} - {description && } - -