diff --git a/.prettierignore b/.prettierignore index b0054f9..235ffe7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -15,3 +15,9 @@ node_modules .analyze.html build + +*.mdx + +LICENSE + +CNAME diff --git a/.prettierrc b/.prettierrc index d30aa4b..e68f2fc 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,7 +1,7 @@ { "useTabs": false, "tabWidth": 2, - "printWidth": 80, + "printWidth": 100, "singleQuote": true, "arrowParens": "always", "semi": true, diff --git a/.stylelintignore b/.stylelintignore index afc9979..6e3708e 100644 --- a/.stylelintignore +++ b/.stylelintignore @@ -11,3 +11,9 @@ index.html .analyze.html build + +*.mdx + +LICENSE + +CNAME diff --git a/commitlint.config.cjs b/commitlint.config.cjs index 52f2783..2c41c81 100644 --- a/commitlint.config.cjs +++ b/commitlint.config.cjs @@ -6,18 +6,7 @@ module.exports = { 'type-enum': [ 2, 'always', - [ - 'feat', - 'fix', - 'docs', - 'style', - 'refactor', - 'perf', - 'test', - 'chore', - 'revert', - 'build' - ] + ['feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'chore', 'revert', 'build'] ], 'type-case': [0], 'type-empty': [0], diff --git a/helpers/submit.ts b/helpers/submit.ts index 418b956..52c62de 100644 --- a/helpers/submit.ts +++ b/helpers/submit.ts @@ -23,11 +23,7 @@ function getHref(path: string) { function writeSubmited(submitedList: string[]) { try { - writeFileSync( - submitedPath, - `export default ${JSON.stringify(submitedList, null, 2)}`, - 'utf-8' - ); + writeFileSync(submitedPath, `export default ${JSON.stringify(submitedList, null, 2)}`, 'utf-8'); } catch (err) { console.log('write fail', err); } diff --git a/helpers/utils.ts b/helpers/utils.ts index 948e52a..6d4d48f 100644 --- a/helpers/utils.ts +++ b/helpers/utils.ts @@ -44,8 +44,7 @@ export const routesPath = resolve('src/routes.tsx'); export const parseRoute = (path: string) => path.split(sep).pop()!.slice(0, -4); -export const replaceFileExtension = (name: string) => - name.slice(0, name.lastIndexOf('.')) + '.tsx'; +export const replaceFileExtension = (name: string) => name.slice(0, name.lastIndexOf('.')) + '.tsx'; export const generateRouteJSONWithArticle = async () => { const paths = await fast.glob(['./src/markdowns/**/*.mdx']); @@ -56,13 +55,9 @@ export const generateRouteJSONWithArticle = async () => { .map((path) => resolve(path)) .forEach((path) => { const route = parseRoute(path); - const { attributes } = frontmatter( - readFileSync(path, 'utf-8') - ); + const { attributes } = frontmatter(readFileSync(path, 'utf-8')); - const aliasPath = path - .replace('./src/markdowns', '@/markdowns') - .replace(/\\/g, '/'); + const aliasPath = path.replace('./src/markdowns', '@/markdowns').replace(/\\/g, '/'); const str = ` { @@ -85,9 +80,7 @@ export const generateRouteJSONWithArticle = async () => { export const getExampleMeta = (path: string) => { const text = readFileSync(path, 'utf-8'); - const match = text - .match(/(?<=\/\/--meta:)([\s\S]*)(?=\/\/--endmeta)/)?.[0] - .trim(); + const match = text.match(/(?<=\/\/--meta:)([\s\S]*)(?=\/\/--endmeta)/)?.[0].trim(); const arr = match!.replace(/\/\/\s/g, '').split(/[\n\r]/); @@ -104,12 +97,7 @@ const template = readFileSync(resolve('./src/coder/Wrapper.tsx'), 'utf-8'); export const generateRouteJSONWithExample = async () => { let result = ''; - async function transform( - dirs: string[], - parent: string, - hierarchy: number, - root: string - ) { + async function transform(dirs: string[], parent: string, hierarchy: number, root: string) { if (hierarchy === 0) { const directory = resolve(parent, `code`); const value = template.replace('base64_coder/Index', `${root}/Index`); @@ -156,9 +144,7 @@ export const generateRouteJSONWithExample = async () => { const newName = replaceFileExtension(name); - const paths = relative(resolve(examples, root), parent) - .split(sep) - .filter(Boolean); + const paths = relative(resolve(examples, root), parent).split(sep).filter(Boolean); const folder = resolve(examples, root, 'code', ...paths); if (!existsSync(folder)) { @@ -207,10 +193,7 @@ export const generateRouteJSON = async () => { }; }; -export const replacePlaceRoute = ( - code: string, - { books, articles, examples }: RoutePlace -) => +export const replacePlaceRoute = (code: string, { books, articles, examples }: RoutePlace) => code .replace('/** placeholder for articles */', articles) .replace('/** placeholder for books */', books) diff --git a/helpers/vite-generate-sitemap.ts b/helpers/vite-generate-sitemap.ts index 1e2c71f..2a0af55 100644 --- a/helpers/vite-generate-sitemap.ts +++ b/helpers/vite-generate-sitemap.ts @@ -25,9 +25,7 @@ function viteGenerateSitemap(): PluginOption { } const routeJSON = await generateRouteJSON(); - const getRoutes = new Function( - `return ${replacePlaceRoute(`[${match[0]}]`, routeJSON)}` - ); + const getRoutes = new Function(`return ${replacePlaceRoute(`[${match[0]}]`, routeJSON)}`); const detailsRoutes = resolveFullRoutes(getRoutes(), '', []); diff --git a/helpers/vite-generateSw.ts b/helpers/vite-generateSw.ts index 802431c..04e82e5 100644 --- a/helpers/vite-generateSw.ts +++ b/helpers/vite-generateSw.ts @@ -79,10 +79,7 @@ declare class Queue { private _syncInProgress; private _requestsAddedDuringSync; - constructor( - name: string, - { forceSyncFallback, onSync, maxRetentionTime }?: QueueOptions - ); + constructor(name: string, { forceSyncFallback, onSync, maxRetentionTime }?: QueueOptions); get name(): string; @@ -131,9 +128,7 @@ export interface CacheDidUpdateCallbackParam { export interface BroadcastCacheUpdateOptions { headersToCheck?: string[]; - generatePayload?: ( - options: CacheDidUpdateCallbackParam - ) => Record; + generatePayload?: (options: CacheDidUpdateCallbackParam) => Record; notifyAllClients?: boolean; } @@ -178,9 +173,7 @@ export interface CachedResponseWillBeUsedCallbackParam { state?: PluginState; } export interface CachedResponseWillBeUsedCallback { - ( - param: CachedResponseWillBeUsedCallbackParam - ): Promise; + (param: CachedResponseWillBeUsedCallbackParam): Promise; } export interface CacheKeyWillBeUsedCallbackParam { @@ -201,9 +194,7 @@ export interface CacheWillUpdateCallbackParam { state?: PluginState; } export interface CacheWillUpdateCallback { - ( - param: CacheWillUpdateCallbackParam - ): Promise; + (param: CacheWillUpdateCallbackParam): Promise; } export interface CachedResponseWillBeUsedCallbackParam { cacheName: string; @@ -214,9 +205,7 @@ export interface CachedResponseWillBeUsedCallbackParam { state?: PluginState; } export interface CachedResponseWillBeUsedCallback { - ( - param: CachedResponseWillBeUsedCallbackParam - ): Promise; + (param: CachedResponseWillBeUsedCallbackParam): Promise; } export interface FetchDidFailCallbackParam { error: Error; @@ -521,9 +510,7 @@ const defaultConfig = { name: 'vite:workbox' }; -export default function vitePluginWorkbox({ - mode -}: ConfigParams): PluginOption { +export default function vitePluginWorkbox({ mode }: ConfigParams): PluginOption { if (mode === 'development') { return defaultConfig; } diff --git a/helpers/vite-prerender.ts b/helpers/vite-prerender.ts index 11de669..7de66e3 100644 --- a/helpers/vite-prerender.ts +++ b/helpers/vite-prerender.ts @@ -29,14 +29,7 @@ const reg = /(?<=export const routes: RouteObject\[\] = \[)([\s\S]*)(?=\];)/; const match = text.match(reg); -const excludeOutPathRewrite = [ - '/', - '/articles', - '/examples', - '/books', - '/coder', - '/profile' -]; +const excludeOutPathRewrite = ['/', '/articles', '/examples', '/books', '/coder', '/profile']; function getMetaTag(meta: ArticleMeta | undefined, route: ResolveRouteObject) { const env = getEnv(); @@ -135,9 +128,7 @@ async function vitePrerender(mode: string) { } const routeJSON = await generateRouteJSON(); - const getRoutes = new Function( - `return ${replacePlaceRoute(`[${match[0]}]`, routeJSON)}` - ); + const getRoutes = new Function(`return ${replacePlaceRoute(`[${match[0]}]`, routeJSON)}`); const detailsRoutes = resolveFullRoutes(getRoutes(), '', []); const routes = detailsRoutes.map((route) => route.fullPath); @@ -174,18 +165,10 @@ async function vitePrerender(mode: string) { renderedRoute.outputPath = 'build' + renderedRoute.originalRoute; } - renderedRoute.html = renderedRoute.html.replace( - ' route.fullPath === renderedRoute.originalRoute - ); + renderedRoute.html = renderedRoute.html.replace(' route.fullPath === renderedRoute.originalRoute); if (route) { renderedRoute.html = renderedRoute.html.replace( '', diff --git a/helpers/vite-route-generator.ts b/helpers/vite-route-generator.ts index 986838b..e5fd8dd 100644 --- a/helpers/vite-route-generator.ts +++ b/helpers/vite-route-generator.ts @@ -1,9 +1,4 @@ -import { - generateRouteJSON, - replacePlaceRoute, - resolve, - routesPath -} from './utils'; +import { generateRouteJSON, replacePlaceRoute, resolve, routesPath } from './utils'; import type { PluginOption } from 'vite'; import { createFilter } from 'vite'; diff --git a/src/App.tsx b/src/App.tsx index 654db1e..ac57960 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,13 +1,6 @@ import { createContext, useEffect, useRef } from 'react'; -import { - Button, - ConfigProvider, - message, - Modal, - notification, - theme -} from 'antd'; +import { Button, ConfigProvider, message, Modal, notification, theme } from 'antd'; import type { MessageInstance } from 'antd/es/message/interface'; import type { HookAPI } from 'antd/es/modal/useModal'; import type { NotificationInstance } from 'antd/es/notification/interface'; @@ -82,9 +75,7 @@ const App: React.FC = (props) => { if (hasLocalStorage('app')) { setLanguage(getStorage('app')?.settings?.language || 'zh-CN'); - setColorScheme( - getStorage('app')?.settings?.colorScheme || 'light' - ); + setColorScheme(getStorage('app')?.settings?.colorScheme || 'light'); } else { setLanguage(language); if (darkModeQuery.matches) { @@ -134,10 +125,7 @@ const App: React.FC = (props) => { const listenerVisibilityChange = () => { setFrontDesk(!window.document.hidden); }; - window.document.addEventListener( - 'visibilitychange', - listenerVisibilityChange - ); + window.document.addEventListener('visibilitychange', listenerVisibilityChange); const cancelGlobalUserTipsEventListener = globalEvent.on( 'user_tips', @@ -152,19 +140,14 @@ const App: React.FC = (props) => { } ); - const cancelListenerReLoad = assetsLoadHandle.reLoadByOnline( - () => !enableServiceWorkerCache - ); + const cancelListenerReLoad = assetsLoadHandle.reLoadByOnline(() => !enableServiceWorkerCache); return () => { cancelListenerReLoad(); cancelGlobalUserTipsEventListener(); cancelGlobalUserAlertEventListener(); darkModeQuery.removeEventListener('change', listenerColorSchemeChange); - window.document.removeEventListener( - 'visibilitychange', - listenerVisibilityChange - ); + window.document.removeEventListener('visibilitychange', listenerVisibilityChange); }; }, []); @@ -179,15 +162,10 @@ const App: React.FC = (props) => { token: { colorPrimary: '#ff6000' }, - algorithm: - colorScheme === 'dark' - ? theme.darkAlgorithm - : theme.defaultAlgorithm + algorithm: colorScheme === 'dark' ? theme.darkAlgorithm : theme.defaultAlgorithm }} > - - {props.children} - + {props.children} ); diff --git a/src/assets/styles/prism-one-dark.css b/src/assets/styles/prism-one-dark.css index 3a2803b..09e5223 100644 --- a/src/assets/styles/prism-one-dark.css +++ b/src/assets/styles/prism-one-dark.css @@ -35,8 +35,7 @@ pre[class*='language-'] { background: hsl(220, 13%, 18%); color: hsl(220, 14%, 71%); text-shadow: 0 1px rgba(0, 0, 0, 0.3); - font-family: 'Fira Code', 'Fira Mono', Menlo, Consolas, 'DejaVu Sans Mono', - monospace; + font-family: 'Fira Code', 'Fira Mono', Menlo, Consolas, 'DejaVu Sans Mono', monospace; direction: ltr; text-align: left; white-space: pre; @@ -311,9 +310,7 @@ div.code-toolbar > .toolbar.toolbar > .toolbar-item > span:focus { /* Hovering over a linkable line number (in the gutter area) */ /* Requires Line Numbers plugin as well */ -pre[id].linkable-line-numbers.linkable-line-numbers - span.line-numbers-rows - > span:hover:before { +pre[id].linkable-line-numbers.linkable-line-numbers span.line-numbers-rows > span:hover:before { background-color: hsla(220, 100%, 80%, 0.04); } diff --git a/src/coder/Wrapper.tsx b/src/coder/Wrapper.tsx index e377eb4..65d66b6 100644 --- a/src/coder/Wrapper.tsx +++ b/src/coder/Wrapper.tsx @@ -30,9 +30,7 @@ function mergeMenu(menu: IMenu[]) { for (let i = 0; i < some.length; i++) { curr.children = [...(curr.children || []), ...(some[i].children || [])]; - curr.children = curr.children.length - ? mergeMenu(curr.children) - : undefined; + curr.children = curr.children.length ? mergeMenu(curr.children) : undefined; } result.push(curr); @@ -109,16 +107,11 @@ function Menu({ items }: { items: IMenu[] }) { [styles.expand]: expands.includes(item.fullPath + item.path) })} > - e.preventDefault()} - title={item.path} - > + e.preventDefault()} title={item.path}>
code.path === curr)!.children!) - ); + return transformMenu(cloneDeep(codes.find((code) => code.path === curr)!.children!)); }, []); const handleChangeLayout = (e: number) => { diff --git a/src/components/Canvas/Canvas.tsx b/src/components/Canvas/Canvas.tsx index ea077dd..a24649b 100644 --- a/src/components/Canvas/Canvas.tsx +++ b/src/components/Canvas/Canvas.tsx @@ -1,23 +1,10 @@ -import { - forwardRef, - memo, - useEffect, - useImperativeHandle, - useRef -} from 'react'; +import { forwardRef, memo, useEffect, useImperativeHandle, useRef } from 'react'; interface ICanvasProps extends React.CanvasHTMLAttributes {} -type ExposeKeys = - | 'beginPath' - | 'moveTo' - | 'arc' - | 'fillText' - | 'stroke' - | 'lineTo'; +type ExposeKeys = 'beginPath' | 'moveTo' | 'arc' | 'fillText' | 'stroke' | 'lineTo'; -export interface CanvasInstance - extends Pick { +export interface CanvasInstance extends Pick { fill(fillRule?: CanvasFillRule): void; lineWidth(lineWidth?: number): number; fillStyle( diff --git a/src/components/ContextMenu/ContextMenu.tsx b/src/components/ContextMenu/ContextMenu.tsx index 8e9a57e..a60c36c 100644 --- a/src/components/ContextMenu/ContextMenu.tsx +++ b/src/components/ContextMenu/ContextMenu.tsx @@ -4,13 +4,11 @@ import { addGlobalListener, sleep } from '@/utils'; import styles from './ContextMenu.module.less'; -export interface SubMenu - extends Omit, 'children'> { +export interface SubMenu extends Omit, 'children'> { name: string; } -export interface Menu - extends Omit, 'children'> { +export interface Menu extends Omit, 'children'> { name: string; // subMenu?: SubMenu[]; icon?: React.ReactNode; diff --git a/src/components/Dialog/Dialog.tsx b/src/components/Dialog/Dialog.tsx index 4b1dfee..45342ee 100644 --- a/src/components/Dialog/Dialog.tsx +++ b/src/components/Dialog/Dialog.tsx @@ -9,21 +9,12 @@ import { import classNames from 'classnames'; -import { - fallbackFullscreen, - isFullScreen, - onFullScreen, - requestFullScreen, - sleep -} from '@/utils'; +import { fallbackFullscreen, isFullScreen, onFullScreen, requestFullScreen, sleep } from '@/utils'; import styles from './Dialog.module.less'; import Icon from '../Icon/Icon'; -export type DialogProps = Omit< - React.HTMLAttributes, - 'open' | 'onClose' ->; +export type DialogProps = Omit, 'open' | 'onClose'>; export interface IDialogProps extends DialogProps { open: boolean; @@ -90,188 +81,172 @@ let savePosition = { y: 0 }; -const Dialog = forwardRef>( - function Dialog(props, ref) { - const { - open, - toolbar = null, - draggable = true, - className = '', - children, - onAnimationEnd, - onMinimize, - onClose, - ...rest - } = props; - - const dialogRef = useRef(null); - const initedRef = useRef(open); - - useImperativeHandle(ref, () => ({ - get dialog() { - return dialogRef.current; - } - })); +const Dialog = forwardRef>(function Dialog(props, ref) { + const { + open, + toolbar = null, + draggable = true, + className = '', + children, + onAnimationEnd, + onMinimize, + onClose, + ...rest + } = props; + + const dialogRef = useRef(null); + const initedRef = useRef(open); + + useImperativeHandle(ref, () => ({ + get dialog() { + return dialogRef.current; + } + })); - useLayoutEffect(() => { - if (open) { - initedRef.current = true; - } + useLayoutEffect(() => { + if (open) { + initedRef.current = true; + } - if (!initedRef.current) { - dialogRef.current!.style.display = 'none'; - dialogRef.current!.parentElement!.style.display = 'none'; - return void 0; - } + if (!initedRef.current) { + dialogRef.current!.style.display = 'none'; + dialogRef.current!.parentElement!.style.display = 'none'; + return void 0; + } - animateStrategy[open ? 'beforeEnter' : 'beforeLeave'](dialogRef.current!); - }, [open]); + animateStrategy[open ? 'beforeEnter' : 'beforeLeave'](dialogRef.current!); + }, [open]); - const _onAnimationEnd = (e: React.AnimationEvent) => { - animateStrategy[open ? 'afterEnter' : 'afterLeave'](dialogRef.current!); - onAnimationEnd?.(e); - }; + const _onAnimationEnd = (e: React.AnimationEvent) => { + animateStrategy[open ? 'afterEnter' : 'afterLeave'](dialogRef.current!); + onAnimationEnd?.(e); + }; - const handleStart = (e: React.MouseEvent) => { - if (!draggable || isFullScreen(dialogRef.current!)) { - return false; - } + const handleStart = (e: React.MouseEvent) => { + if (!draggable || isFullScreen(dialogRef.current!)) { + return false; + } - let prev = { x: e.pageX, y: e.pageY }; + let prev = { x: e.pageX, y: e.pageY }; - function mouseMove(e: MouseEvent) { - const movementX = e.pageX - prev.x; - const movementY = e.pageY - prev.y; + function mouseMove(e: MouseEvent) { + const movementX = e.pageX - prev.x; + const movementY = e.pageY - prev.y; - savePosition = { - x: savePosition.x + movementX, - y: savePosition.y + movementY - }; + savePosition = { + x: savePosition.x + movementX, + y: savePosition.y + movementY + }; - // TODO: Browsers that support translate do not have a high occupancy rate on the market. - dialogRef.current!.style.translate = `${savePosition.x}px ${savePosition.y}px`; + // TODO: Browsers that support translate do not have a high occupancy rate on the market. + dialogRef.current!.style.translate = `${savePosition.x}px ${savePosition.y}px`; - prev = { - x: e.pageX, - y: e.pageY - }; - } + prev = { + x: e.pageX, + y: e.pageY + }; + } - function mouoseUp() { - window.document.documentElement.removeEventListener( - 'mousemove', - mouseMove - ); - window.document.documentElement.removeEventListener( - 'mouseup', - mouoseUp - ); - } + function mouoseUp() { + window.document.documentElement.removeEventListener('mousemove', mouseMove); + window.document.documentElement.removeEventListener('mouseup', mouoseUp); + } - window.document.documentElement.addEventListener('mousemove', mouseMove); - window.document.documentElement.addEventListener('mouseup', mouoseUp); - }; + window.document.documentElement.addEventListener('mousemove', mouseMove); + window.document.documentElement.addEventListener('mouseup', mouoseUp); + }; - function Header() { - const [full, setFull] = useState(false); + function Header() { + const [full, setFull] = useState(false); - useEffect(() => { - return onFullScreen(() => { - setFull(isFullScreen(dialogRef.current!)); - }, dialogRef.current!); - }, []); + useEffect(() => { + return onFullScreen(() => { + setFull(isFullScreen(dialogRef.current!)); + }, dialogRef.current!); + }, []); - const _onMinimize = () => { - onMinimize?.(); + const _onMinimize = () => { + onMinimize?.(); - if (full) { - fallbackFullscreen(); - } - }; + if (full) { + fallbackFullscreen(); + } + }; - const onMaximize = () => { - const ele = dialogRef.current!; + const onMaximize = () => { + const ele = dialogRef.current!; - if (!isFullScreen(ele)) { - ele.style.translate = ''; - requestFullScreen(ele); - setFull(true); - } - }; - const _onRestore = () => { - const ele = dialogRef.current!; - - if (isFullScreen(ele)) { - ele.style.translate = `${savePosition.x}px ${savePosition.y}px`; - fallbackFullscreen(); - setFull(false); - } - }; + if (!isFullScreen(ele)) { + ele.style.translate = ''; + requestFullScreen(ele); + setFull(true); + } + }; + const _onRestore = () => { + const ele = dialogRef.current!; - const _onClose = () => { - onClose?.(); - }; + if (isFullScreen(ele)) { + ele.style.translate = `${savePosition.x}px ${savePosition.y}px`; + fallbackFullscreen(); + setFull(false); + } + }; - return ( - <> -
-
-
- {toolbar} -
- -
- - - - - - -
-
- - ); - } + const _onClose = () => { + onClose?.(); + }; return ( -
-
-
- - {children} -
-
+ <> +
+
+
+ {toolbar} +
+ +
+ + + + + + +
+
+ ); } -); + + return ( +
+
+
+ + {children} +
+
+ ); +}); export default Dialog; diff --git a/src/components/Icon/Icon.tsx b/src/components/Icon/Icon.tsx index c3e2e27..06e4eb2 100644 --- a/src/components/Icon/Icon.tsx +++ b/src/components/Icon/Icon.tsx @@ -25,10 +25,7 @@ const Icon: React.FC> = (props) => { return ( - diff --git a/src/examples/base64_coder/Index.tsx b/src/examples/base64_coder/Index.tsx index 56856a9..9501862 100644 --- a/src/examples/base64_coder/Index.tsx +++ b/src/examples/base64_coder/Index.tsx @@ -54,12 +54,7 @@ export default function Base64_Coder() { return (
-