mirror of
https://github.com/Kxsso/jcutmirror.git
synced 2026-02-09 01:16:58 +08:00
合并浙大上游仓库
This commit is contained in:
@@ -13,13 +13,15 @@ module.exports = {
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: './tsconfig.json',
|
||||
tsconfigRootDir: './',
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['react', '@typescript-eslint', 'prettier'],
|
||||
plugins: ['react', '@typescript-eslint', 'import', 'prettier'],
|
||||
rules: {
|
||||
// needed by prettier
|
||||
'prettier/prettier': 'warn',
|
||||
|
||||
2
.github/workflows/testbuild.yml
vendored
2
.github/workflows/testbuild.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
node-version: [20.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
image: node:lts-bullseye
|
||||
image:
|
||||
name: node:20
|
||||
pull_policy: if-not-present
|
||||
|
||||
stages:
|
||||
- build
|
||||
@@ -8,12 +10,16 @@ gatsby-build:
|
||||
stage: build
|
||||
variables:
|
||||
CHOKIDAR_USEPOLLING: 1
|
||||
GATSBY_TELEMETRY_DISABLED: 1
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
- .npm/
|
||||
script:
|
||||
- bash cached-restore.sh
|
||||
- yarn run build
|
||||
- apt-get update && apt-get install -y libvips42 libvips-dev
|
||||
- npm config set registry https://registry.npmmirror.com
|
||||
- npm install -g npm@10.5.1
|
||||
- npm ci --cache .npm --prefer-offline
|
||||
- npm run build
|
||||
artifacts:
|
||||
paths:
|
||||
- public
|
||||
|
||||
@@ -1 +1,5 @@
|
||||
import './src/styles/global.scss';
|
||||
import React from 'react';
|
||||
import RootLayout from './src/utils/root-layout';
|
||||
|
||||
export const wrapRootElement = ({ element }) => <RootLayout>{element}</RootLayout>
|
||||
|
||||
@@ -16,20 +16,6 @@ module.exports = {
|
||||
assetPrefix: config.assetPrefix,
|
||||
pathPrefix: config.pathPrefix,
|
||||
plugins: [
|
||||
{
|
||||
resolve: `gatsby-theme-material-ui`,
|
||||
options: {
|
||||
webFontsConfig: {
|
||||
fonts: {
|
||||
google: [
|
||||
{
|
||||
family: `Metrophobic`
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
resolve: 'gatsby-source-filesystem',
|
||||
options: {
|
||||
@@ -57,7 +43,7 @@ module.exports = {
|
||||
mdxOptions: {
|
||||
remarkPlugins: [
|
||||
// Add GitHub Flavored Markdown (GFM) support
|
||||
// Warning: Most of the remark ecosystem is ESM which means that packages
|
||||
// Warning: Most of the remark ecosystem is ESM which means that packages
|
||||
// like remark-gfm don’t work out of the box with Gatsby v5. To make remark-gfm
|
||||
// compatible with the current Gatsby version, we have to use an old version of
|
||||
// remark-gfm. Please take care in future updates.
|
||||
@@ -72,11 +58,11 @@ module.exports = {
|
||||
rule: {
|
||||
include: /icons/,
|
||||
omitKeys: [
|
||||
'inkscapePageshadow', 'inkscapePageopacity', 'inkscapePagecheckerboard',
|
||||
'inkscapeZoom', 'inkscapeCx', 'inkscapeCy', 'inkscapeWindowWidth', 'inkscapeWindowHeight',
|
||||
'inkscapeWindowX', 'inkscapeWindowY', 'inkscapeWindowMaximized', 'inkscapeCurrentLayer',
|
||||
'inkscapePageshadow', 'inkscapePageopacity', 'inkscapePagecheckerboard',
|
||||
'inkscapeZoom', 'inkscapeCx', 'inkscapeCy', 'inkscapeWindowWidth', 'inkscapeWindowHeight',
|
||||
'inkscapeWindowX', 'inkscapeWindowY', 'inkscapeWindowMaximized', 'inkscapeCurrentLayer',
|
||||
'sodipodiNodetypes', 'sodipodiDocname', 'inkscapeVersion', 'xmlnsInkscape', 'xmlnsSodipodi',
|
||||
'xmlnsSvg',
|
||||
'xmlnsSvg',
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -113,7 +99,6 @@ module.exports = {
|
||||
icon: 'resource/icons/favicon.svg',
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-preact`,
|
||||
`gatsby-plugin-sass`,
|
||||
{
|
||||
resolve: "gatsby-plugin-sitemap",
|
||||
|
||||
@@ -2,6 +2,7 @@ const { match, compile } = require("path-to-regexp");
|
||||
const { createFilePath } = require(`gatsby-source-filesystem`)
|
||||
const { createContentDigest } = require(`gatsby-core-utils`)
|
||||
const config = require('./config');
|
||||
const path = require("path");
|
||||
|
||||
const mdxResolverPassthrough = (fieldName) => async (
|
||||
source,
|
||||
@@ -194,3 +195,13 @@ exports.createPages = async ({ graphql, actions, reporter }) => {
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
exports.onCreateWebpackConfig = ({ actions }) => {
|
||||
actions.setWebpackConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
'~': path.resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
5
gatsby-ssr.js
Normal file
5
gatsby-ssr.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import './src/styles/global.scss';
|
||||
import React from 'react';
|
||||
import RootLayout from './src/utils/root-layout';
|
||||
|
||||
export const wrapRootElement = ({ element }) => <RootLayout>{element}</RootLayout>
|
||||
93
package.json
93
package.json
@@ -17,67 +17,66 @@
|
||||
"lint-check": "eslint src/**/*"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.9.0",
|
||||
"@emotion/styled": "^11.8.1",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/server": "^11.11.0",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@fontsource/poppins": "^4.5.10",
|
||||
"@formatjs/intl-displaynames": "^5.4.3",
|
||||
"@iconify/icons-file-icons": "^1.2.3",
|
||||
"@iconify/icons-logos": "^1.2.36",
|
||||
"@iconify/icons-mdi": "^1.2.44",
|
||||
"@iconify/icons-mdi": "^1.2.48",
|
||||
"@iconify/icons-simple-icons": "^1.2.74",
|
||||
"@iconify/react": "^3.2.1",
|
||||
"@iconify/react": "^3.2.2",
|
||||
"@mdx-js/mdx": "^3.0.1",
|
||||
"@mdx-js/react": "^2.3.0",
|
||||
"@mui/icons-material": "^5.6.2",
|
||||
"@mui/material": "^5.6.3",
|
||||
"gatsby": "^5.9.1",
|
||||
"gatsby-plugin-manifest": "^5.6.0",
|
||||
"gatsby-plugin-mdx": "^5.6.0",
|
||||
"gatsby-plugin-preact": "^7.6.1",
|
||||
"@mui/icons-material": "^5.15.15",
|
||||
"@mui/material": "^5.15.15",
|
||||
"gatsby": "^5.13.3",
|
||||
"gatsby-plugin-manifest": "^5.13.1",
|
||||
"gatsby-plugin-mdx": "^5.13.1",
|
||||
"gatsby-plugin-react-helmet": "^6.13.1",
|
||||
"gatsby-plugin-react-i18next": "^3.0.1",
|
||||
"gatsby-plugin-react-svg": "^3.1.0",
|
||||
"gatsby-plugin-sass": "^6.6.0",
|
||||
"gatsby-plugin-sitemap": "^6.7.0",
|
||||
"gatsby-source-filesystem": "^5.6.0",
|
||||
"gatsby-theme-material-ui": "^5.2.0",
|
||||
"gatsby-theme-material-ui-top-layout": "^5.2.0",
|
||||
"i18next": "^21.6.16",
|
||||
"js-search": "^2.0.0",
|
||||
"gatsby-plugin-react-svg": "^3.3.0",
|
||||
"gatsby-plugin-sass": "^6.13.1",
|
||||
"gatsby-plugin-sitemap": "^6.13.1",
|
||||
"gatsby-source-filesystem": "^5.13.1",
|
||||
"i18next": "^22.5.1",
|
||||
"js-search": "^2.0.1",
|
||||
"natsort": "^2.0.3",
|
||||
"path-to-regexp": "^6.2.0",
|
||||
"preact": "^10.12.1",
|
||||
"preact-render-to-string": "^5.2.6",
|
||||
"prism-react-renderer": "^1.3.1",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0",
|
||||
"path-to-regexp": "^6.2.2",
|
||||
"prism-react-renderer": "^1.3.5",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-i18next": "^11.16.7",
|
||||
"remark-gfm": "^1",
|
||||
"sass": "^1.53.0"
|
||||
"react-i18next": "^12.3.1",
|
||||
"remark-gfm": "^1.0.0",
|
||||
"sass": "^1.74.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.17.10",
|
||||
"@babel/plugin-transform-typescript": "^7.16.8",
|
||||
"@types/js-search": "^1.4.0",
|
||||
"@types/mdx": "^2.0.1",
|
||||
"@types/mdx-js__react": "^1.5.5",
|
||||
"@types/node": "^18.0.0",
|
||||
"@types/react": "^18.0.14",
|
||||
"@types/react-dom": "^18.0.5",
|
||||
"@typescript-eslint/eslint-plugin": "^5.28.0",
|
||||
"@typescript-eslint/parser": "^5.28.0",
|
||||
"@babel/cli": "^7.24.1",
|
||||
"@babel/plugin-transform-typescript": "^7.24.4",
|
||||
"@types/js-search": "^1.4.4",
|
||||
"@types/mdx": "^2.0.12",
|
||||
"@types/mdx-js__react": "^1.5.8",
|
||||
"@types/node": "^18.19.31",
|
||||
"@types/react": "^18.2.75",
|
||||
"@types/react-dom": "^18.2.24",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
"babel-plugin-i18next-extract": "^0.8.3",
|
||||
"eslint": "^8.2.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-airbnb": "19.0.4",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-import-resolver-typescript": "^3.2.1",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-react": "^7.30.0",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
"eslint-config-prettier": "^8.10.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-react": "^7.34.1",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"prettier": "2.7.1",
|
||||
"typescript": "^4.7.3"
|
||||
"prettier": "^3.2.5",
|
||||
"prettier-eslint": "^16.3.0",
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -38,13 +38,18 @@ export default ({ children, codeStyle, language }: CodeBlockProps) => {
|
||||
...codeStyle,
|
||||
}}
|
||||
>
|
||||
{tokens.map((line, i) => (
|
||||
<div key={i} {...getLineProps({ line, key: i })}>
|
||||
{line.map((token, key) => (
|
||||
<span key={key} {...getTokenProps({ token, key })} />
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
{tokens.map((line, i) => {
|
||||
if (line.length === 1 && line[0].content.indexOf('\u200b') > -1) {
|
||||
return <br />;
|
||||
}
|
||||
return (
|
||||
<div key={i} {...getLineProps({ line, key: i })}>
|
||||
{line.map((token, key) => (
|
||||
<span key={key} {...getTokenProps({ token, key })} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</code>
|
||||
)}
|
||||
</Highlight>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { PaletteMode, ThemeOptions } from '@mui/material';
|
||||
import { PaletteMode, ThemeOptions, createTheme } from '@mui/material';
|
||||
import '@fontsource/poppins';
|
||||
|
||||
export default function configTheme(mode: PaletteMode): ThemeOptions {
|
||||
function configTheme(mode: PaletteMode): ThemeOptions {
|
||||
return {
|
||||
palette:
|
||||
mode === 'light'
|
||||
@@ -91,6 +91,24 @@ export default function configTheme(mode: PaletteMode): ThemeOptions {
|
||||
};
|
||||
}
|
||||
|
||||
export const lightTheme = createTheme(
|
||||
{
|
||||
palette: {
|
||||
mode: 'light',
|
||||
},
|
||||
},
|
||||
configTheme('light')
|
||||
);
|
||||
|
||||
export const darkTheme = createTheme(
|
||||
{
|
||||
palette: {
|
||||
mode: 'dark',
|
||||
},
|
||||
},
|
||||
configTheme('dark')
|
||||
);
|
||||
|
||||
/* the code below decares customized color */
|
||||
|
||||
declare module '@mui/material/styles' {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import React from 'react';
|
||||
import { Card, Grid, Typography } from '@mui/material';
|
||||
import Card from '@mui/material/Card';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import AlbumIcon from '@mui/icons-material/Album';
|
||||
import { Trans } from 'gatsby-plugin-react-i18next';
|
||||
import { CardActionArea } from 'gatsby-theme-material-ui';
|
||||
import { LinkCardActionArea as CardActionArea } from './link-mui-components';
|
||||
|
||||
export interface FileProps {
|
||||
name: string;
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import { Box, Card, CardContent, Grid, Typography } from '@mui/material';
|
||||
import { CardActionArea } from 'gatsby-theme-material-ui';
|
||||
import Box from '@mui/material/Box';
|
||||
import Card from '@mui/material/Card';
|
||||
import CardContent from '@mui/material/CardContent';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import * as React from 'react';
|
||||
import { LinkCardActionArea as CardActionArea } from './link-mui-components';
|
||||
|
||||
export type mirrorBrief = {
|
||||
name: string;
|
||||
|
||||
39
src/components/link-mui-components.tsx
Normal file
39
src/components/link-mui-components.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import React, { ForwardedRef } from 'react';
|
||||
import Button from '@mui/material/Button';
|
||||
import CardActionArea from '@mui/material/CardActionArea';
|
||||
import Link from '@mui/material/Link';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import { navigate } from 'gatsby';
|
||||
import { ButtonBaseProps } from '@mui/material';
|
||||
|
||||
interface LinkProps {
|
||||
to?: string;
|
||||
}
|
||||
|
||||
function linkifyComponent<T, PropType>(
|
||||
ButtonBaseComponent: React.ComponentType<ButtonBaseProps & PropType>
|
||||
) {
|
||||
const f = (
|
||||
props: ButtonBaseProps & PropType & LinkProps,
|
||||
ref: ForwardedRef<T>
|
||||
) => {
|
||||
const propOnClick = props.onClick;
|
||||
const clickHandler: React.MouseEventHandler<HTMLButtonElement> = event => {
|
||||
if (propOnClick) propOnClick(event);
|
||||
if (props.to) navigate(props.to);
|
||||
};
|
||||
return (
|
||||
<ButtonBaseComponent {...props} onClick={clickHandler} ref={ref}>
|
||||
{props.children}
|
||||
</ButtonBaseComponent>
|
||||
);
|
||||
};
|
||||
return React.forwardRef(f);
|
||||
}
|
||||
|
||||
const LinkButton = linkifyComponent(Button);
|
||||
const LinkCardActionArea = linkifyComponent(CardActionArea);
|
||||
const LinkIconButton = linkifyComponent(IconButton);
|
||||
const LinkLink = linkifyComponent(Link);
|
||||
|
||||
export { LinkProps, LinkButton, LinkCardActionArea, LinkIconButton, LinkLink };
|
||||
@@ -1,9 +1,9 @@
|
||||
import InfoIcon from '@mui/icons-material/Info';
|
||||
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
||||
import { Tooltip } from '@mui/material';
|
||||
import { IconButton } from 'gatsby-theme-material-ui';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import * as React from 'react';
|
||||
import { LinkIconButton as IconButton } from './link-mui-components';
|
||||
import { usePrefs } from './preferences-context';
|
||||
|
||||
const nameMode = {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { Card, Grid, Typography, Tooltip } from '@mui/material';
|
||||
import Card from '@mui/material/Card';
|
||||
import Grid from '@mui/material/Grid';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import { useI18next } from 'gatsby-plugin-react-i18next';
|
||||
import { CardActionArea } from 'gatsby-theme-material-ui';
|
||||
import * as React from 'react';
|
||||
import VerifiedIcon from '@mui/icons-material/Verified';
|
||||
import { LinkCardActionArea as CardActionArea } from './link-mui-components';
|
||||
import { Locale, Mirror } from '../types/mirror';
|
||||
import StatusIndicator from './status-indicator';
|
||||
import { getUrl } from '../utils/url';
|
||||
import { usePrefs } from './preferences-context';
|
||||
import VerifiedIcon from '@mui/icons-material/Verified';
|
||||
import officialCertificatedMirrorList from '../utils/official-certificated-mirror-list';
|
||||
|
||||
const SearchItemCard = (props: { queryItem: Mirror }) => {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import React from 'react';
|
||||
import { JSX } from 'preact';
|
||||
import { useStaticQuery, graphql } from 'gatsby';
|
||||
import { useTheme } from '@mui/material';
|
||||
import { useI18next } from 'gatsby-plugin-react-i18next';
|
||||
|
||||
type MetaProps = JSX.IntrinsicElements['meta'];
|
||||
type MetaProps = React.JSX.IntrinsicElements['meta'];
|
||||
|
||||
const Helmet: React.FC = ({children, title, meta}) => {
|
||||
const {languages, language, originalPath, defaultLanguage, siteUrl = ''} = useI18next();
|
||||
@@ -16,11 +15,7 @@ const Helmet: React.FC = ({children, title, meta}) => {
|
||||
<>
|
||||
<html lang={language} />
|
||||
<title>{title}</title>
|
||||
{
|
||||
meta?.map((m: MetaProps) => (
|
||||
<meta {...m} />
|
||||
))
|
||||
}
|
||||
{meta?.map((m: MetaProps, i: number) => <meta {...m} key={i}/>)}
|
||||
<link rel="canonical" href={createUrlWithLang(language)} />
|
||||
{languages.map((lng) => (
|
||||
<link rel="alternate" key={lng} href={createUrlWithLang(lng)} hrefLang={lng} />
|
||||
|
||||
@@ -5,14 +5,14 @@ import {
|
||||
} from '@mui/material/styles';
|
||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||
import * as React from 'react';
|
||||
import configTheme from './config-theme';
|
||||
import { lightTheme, darkTheme } from './config-theme';
|
||||
import { readCache, writeCache } from '../utils/cache';
|
||||
|
||||
export type ThemeMode = PaletteMode | 'auto';
|
||||
|
||||
export declare type ThemeContextInterface = [
|
||||
ThemeMode,
|
||||
(mode: ThemeMode) => void
|
||||
(mode: ThemeMode) => void,
|
||||
];
|
||||
|
||||
export const ThemeContext = React.createContext<ThemeContextInterface | null>(
|
||||
@@ -27,11 +27,12 @@ export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
const [mode, setMode] = React.useState<ThemeMode>(savedMode);
|
||||
|
||||
let paletteMode: PaletteMode;
|
||||
// ensure renders execute equal number of hooks
|
||||
const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
|
||||
const prefersLight = useMediaQuery('(prefers-color-scheme: light)');
|
||||
if (mode === 'auto') {
|
||||
// wait for media query result stable
|
||||
// ref: https://github.com/mui/material-ui/issues/15588#issuecomment-567803082
|
||||
const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
|
||||
const prefersLight = useMediaQuery('(prefers-color-scheme: light)');
|
||||
if (prefersDark !== !prefersLight) return null;
|
||||
const preferredMode = prefersDark ? 'dark' : 'light';
|
||||
paletteMode = preferredMode;
|
||||
@@ -39,18 +40,7 @@ export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
paletteMode = mode;
|
||||
}
|
||||
|
||||
const theme = React.useMemo(
|
||||
() =>
|
||||
createTheme(
|
||||
{
|
||||
palette: {
|
||||
mode: paletteMode,
|
||||
},
|
||||
},
|
||||
configTheme(paletteMode)
|
||||
),
|
||||
[paletteMode]
|
||||
);
|
||||
const theme = paletteMode === 'light' ? lightTheme : darkTheme;
|
||||
|
||||
const updateMode = (newMode: ThemeMode) => {
|
||||
setMode(newMode);
|
||||
|
||||
@@ -2,9 +2,9 @@ import Brightness4Icon from '@mui/icons-material/Brightness4';
|
||||
import BrightnessAutoIcon from '@mui/icons-material/BrightnessAuto';
|
||||
import BrightnessHighIcon from '@mui/icons-material/BrightnessHigh';
|
||||
import ToolTip from '@mui/material/Tooltip';
|
||||
import { IconButton } from 'gatsby-theme-material-ui';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LinkIconButton as IconButton } from './link-mui-components';
|
||||
import { ThemeMode, useMode } from './theme-context';
|
||||
|
||||
export default () => {
|
||||
|
||||
236
src/components/ubuntu-config-generator.tsx
Normal file
236
src/components/ubuntu-config-generator.tsx
Normal file
@@ -0,0 +1,236 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
FormControl,
|
||||
InputLabel,
|
||||
Select,
|
||||
MenuItem,
|
||||
Box,
|
||||
Grid,
|
||||
Typography,
|
||||
FormControlLabel,
|
||||
Switch,
|
||||
FormGroup,
|
||||
} from '@mui/material';
|
||||
import { Trans } from 'gatsby-plugin-react-i18next';
|
||||
import CodeBlock from './code-block';
|
||||
|
||||
const ubuntuVersionMap: Record<number | string, string> = {
|
||||
2404: 'noble',
|
||||
2310: 'mantic',
|
||||
2304: 'lunar',
|
||||
2210: 'kinetic',
|
||||
2204: 'jammy',
|
||||
2004: 'focal',
|
||||
1804: 'bionic',
|
||||
1604: 'xenial',
|
||||
1404: 'trusty',
|
||||
};
|
||||
|
||||
const isLTSVersion = (version: number) => {
|
||||
return Math.floor(version / 100) % 2 === 0 && version % 100 === 4;
|
||||
};
|
||||
|
||||
const configGenOld = (
|
||||
version: number | string,
|
||||
enableHTTPS: boolean,
|
||||
enableSrc: boolean,
|
||||
enableProposed: boolean,
|
||||
enableSecurity: boolean,
|
||||
ubuntuVariant: string
|
||||
) => {
|
||||
const ubuntuName = ubuntuVersionMap[version];
|
||||
const httpProtocol = enableHTTPS ? 'https' : 'http';
|
||||
const debSrcText = enableSrc ? '' : '# ';
|
||||
const proposedText = enableProposed ? '' : '# ';
|
||||
const securityRepo = enableSecurity
|
||||
? 'mirrors.jcut.edu.cn'
|
||||
: 'security.ubuntu.com';
|
||||
return `deb ${httpProtocol}://mirrors.jcut.edu.cn/${ubuntuVariant}/ ${ubuntuName} main restricted universe multiverse
|
||||
${debSrcText}deb-src ${httpProtocol}://mirrors.jcut.edu.cn/${ubuntuVariant}/ ${ubuntuName} main restricted universe multiverse
|
||||
deb ${httpProtocol}://mirrors.jcut.edu.cn/${ubuntuVariant}/ ${ubuntuName}-updates main restricted universe multiverse
|
||||
${debSrcText}deb-src ${httpProtocol}://mirrors.jcut.edu.cn/${ubuntuVariant}/ ${ubuntuName}-updates main restricted universe multiverse
|
||||
deb ${httpProtocol}://mirrors.jcut.edu.cn/${ubuntuVariant}/ ${ubuntuName}-backports main restricted universe multiverse
|
||||
${debSrcText}deb-src ${httpProtocol}://mirrors.jcut.edu.cn/${ubuntuVariant}/ ${ubuntuName}-backports main restricted universe multiverse
|
||||
|
||||
deb ${httpProtocol}://${securityRepo}/${ubuntuVariant}/ ${ubuntuName}-security main restricted universe multiverse
|
||||
${debSrcText}deb-src ${httpProtocol}://${securityRepo}/${ubuntuVariant}/ ${ubuntuName}-security main restricted universe multiverse
|
||||
${proposedText}deb ${httpProtocol}://mirrors.jcut.edu.cn/${ubuntuVariant}/ ${ubuntuName}-proposed main restricted universe multiverse
|
||||
${proposedText}${debSrcText}deb-src ${httpProtocol}://mirrors.jcut.edu.cn/${ubuntuVariant}/ ${ubuntuName}-proposed main restricted universe multiverse`;
|
||||
};
|
||||
|
||||
const configGenNew = (
|
||||
version: number | string,
|
||||
enableHTTPS: boolean,
|
||||
enableSrc: boolean,
|
||||
enableProposed: boolean,
|
||||
enableSecurity: boolean,
|
||||
ubuntuVariant: string
|
||||
) => {
|
||||
const ubuntuName = ubuntuVersionMap[version];
|
||||
const httpProtocol = enableHTTPS ? 'https' : 'http';
|
||||
const debSrcText = enableSrc ? ' deb-src' : '';
|
||||
const securityRepo = enableSecurity
|
||||
? 'mirrors.zju.edu.cn'
|
||||
: 'security.ubuntu.com';
|
||||
let sources = `Types: deb${debSrcText}
|
||||
URIs: ${httpProtocol}://mirrors.jcut.edu.cn/${ubuntuVariant}/
|
||||
Suites: ${ubuntuName} ${ubuntuName}-updates ${ubuntuName}-backports
|
||||
Components: main restricted universe multiverse
|
||||
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
|
||||
\u200b
|
||||
Types: deb${debSrcText}
|
||||
URIs: ${httpProtocol}://${securityRepo}/${ubuntuVariant}/
|
||||
Suites: ${ubuntuName}-security
|
||||
Components: main restricted universe multiverse
|
||||
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
|
||||
`;
|
||||
if (enableProposed) {
|
||||
sources += `\u200b
|
||||
Types: deb${debSrcText}
|
||||
URIs: ${httpProtocol}://mirrors.jcut.edu.cn/${ubuntuVariant}/
|
||||
Suites: ${ubuntuName}-proposed
|
||||
Components: main restricted universe multiverse
|
||||
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
|
||||
`;
|
||||
}
|
||||
return sources;
|
||||
};
|
||||
|
||||
export default ({ ubuntuVariant }: { ubuntuVariant: string }) => {
|
||||
const [version, setVersion] = useState(
|
||||
Object.keys(ubuntuVersionMap)
|
||||
.reverse()
|
||||
.filter(v => isLTSVersion(parseInt(v, 10)))[0]
|
||||
);
|
||||
const [enableHTTPS, setEnableHTTPS] = useState(true);
|
||||
const [enableSrc, setEnableSrc] = useState(false);
|
||||
const [enableProposed, setEnableProposed] = useState(false);
|
||||
const [enableSecurity, setEnableSecurity] = useState(true);
|
||||
const shouldUseNewConf = () => parseInt(version, 10) >= 2404;
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Grid
|
||||
container
|
||||
direction="row"
|
||||
justifyContent="flex-start"
|
||||
alignItems="flex-end"
|
||||
>
|
||||
<Grid item sx={{ mb: 1 }}>
|
||||
<Typography component="p">请选择您的 Ubuntu 版本:</Typography>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<FormControl variant="standard" sx={{ m: 1, minWidth: 120 }}>
|
||||
<InputLabel id="demo-simple-select-helper-label">
|
||||
<Trans>版本</Trans>
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="demo-simple-select-helper-label"
|
||||
id="demo-simple-select-helper"
|
||||
label="Age"
|
||||
onChange={event => {
|
||||
setVersion(event.target.value as string);
|
||||
}}
|
||||
defaultValue={version}
|
||||
>
|
||||
{Object.keys(ubuntuVersionMap)
|
||||
.reverse()
|
||||
.map((v: string) => {
|
||||
const item = parseInt(v, 10);
|
||||
let desc = (item / 100).toFixed(2);
|
||||
if (isLTSVersion(item)) desc += ' LTS';
|
||||
desc += ` (${ubuntuVersionMap[item]})`;
|
||||
return (
|
||||
<MenuItem key={item} value={item}>
|
||||
{desc}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<FormGroup>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={enableHTTPS}
|
||||
onChange={e => setEnableHTTPS(e.target.checked)}
|
||||
/>
|
||||
}
|
||||
label="启用 HTTPS (容器镜像可能不支持)"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={enableSrc}
|
||||
onChange={e => setEnableSrc(e.target.checked)}
|
||||
/>
|
||||
}
|
||||
label="启用源码源(默认禁用以提高速度)"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={enableProposed}
|
||||
onChange={e => setEnableProposed(e.target.checked)}
|
||||
/>
|
||||
}
|
||||
label="启用预发布软件源(不建议启用)"
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
checked={enableSecurity}
|
||||
onChange={e => setEnableSecurity(e.target.checked)}
|
||||
/>
|
||||
}
|
||||
label="启用安全更新镜像(仅推荐校网内启用)"
|
||||
/>
|
||||
</FormGroup>
|
||||
<Grid container direction="row" my={2}>
|
||||
<Typography>该版本 Ubuntu 的默认软件源配置文件是</Typography>
|
||||
<code
|
||||
style={{ margin: '0 0.5rem', fontWeight: 'bold', color: 'brown' }}
|
||||
>
|
||||
{shouldUseNewConf()
|
||||
? '/etc/apt/sources.list.d/ubuntu.sources'
|
||||
: '/etc/apt/sources.list'}
|
||||
</code>
|
||||
<Typography>
|
||||
。将系统自带的该文件做个备份,将该文件替换为下面内容,即可使用我们的软件源镜像。
|
||||
</Typography>
|
||||
{shouldUseNewConf() && (
|
||||
<>
|
||||
<Typography style={{ fontWeight: 'bold' }}>
|
||||
如果您从旧版本 Ubuntu 升级到该版本,可能需要同时备份并清除
|
||||
</Typography>
|
||||
<code style={{ margin: '0 0.5rem', fontWeight: 'bold' }}>
|
||||
/etc/apt/sources.list
|
||||
</code>
|
||||
<Typography style={{ fontWeight: 'bold' }}>的内容。</Typography>
|
||||
</>
|
||||
)}
|
||||
</Grid>
|
||||
<CodeBlock language="bash">
|
||||
{shouldUseNewConf()
|
||||
? configGenNew(
|
||||
version,
|
||||
enableHTTPS,
|
||||
enableSrc,
|
||||
enableProposed,
|
||||
enableSecurity,
|
||||
ubuntuVariant
|
||||
)
|
||||
: configGenOld(
|
||||
version,
|
||||
enableHTTPS,
|
||||
enableSrc,
|
||||
enableProposed,
|
||||
enableSecurity,
|
||||
ubuntuVariant
|
||||
)}
|
||||
</CodeBlock>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
import CssBaseline from '@mui/material/CssBaseline';
|
||||
import Viewport from 'gatsby-theme-material-ui-top-layout/src/components/viewport';
|
||||
import React from 'react';
|
||||
import { ThemeProvider } from '../components/theme-context';
|
||||
import { PrefsProvider } from '../components/preferences-context';
|
||||
|
||||
export default function wrapWithProvider({
|
||||
element,
|
||||
}: {
|
||||
element: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<React.StrictMode>
|
||||
<Viewport />
|
||||
<PrefsProvider>
|
||||
<ThemeProvider>
|
||||
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
|
||||
<CssBaseline />
|
||||
{element}
|
||||
</ThemeProvider>
|
||||
</PrefsProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
||||
7
src/pages/404.tsx
Normal file
7
src/pages/404.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
const NotFoundPage = () => {
|
||||
return <h1>Page Not Found</h1>;
|
||||
};
|
||||
|
||||
export default NotFoundPage;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Box, Chip, Grid, Link, Typography } from '@mui/material';
|
||||
import { Box, Chip, ChipProps, Grid, Link, Typography } from '@mui/material';
|
||||
import { graphql } from 'gatsby';
|
||||
import { Trans, useI18next } from 'gatsby-plugin-react-i18next';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
@@ -9,7 +9,7 @@ import SearchTable from '../components/search-table';
|
||||
import NavBar from '../components/nav-bar';
|
||||
import Seo from '../components/seo';
|
||||
import ThemeIconButton from '../components/theme-icon-button';
|
||||
import { Mirror, MirrorDto } from '../types/mirror';
|
||||
import { Locale, Mirror, MirrorDto } from '../types/mirror';
|
||||
import frequentlyUsedMirror from '../utils/frequently-used-mirror-list';
|
||||
import { getUrl } from '../utils/url';
|
||||
import { readCache, writeCache } from '../utils/cache';
|
||||
@@ -40,7 +40,12 @@ interface Data {
|
||||
};
|
||||
}
|
||||
|
||||
const networkMap = {
|
||||
const networkMap: {
|
||||
[value: number]: {
|
||||
text: string;
|
||||
color: ChipProps['color'];
|
||||
};
|
||||
} = {
|
||||
0: {
|
||||
text: '全新版本',
|
||||
color: 'primary',
|
||||
@@ -124,12 +129,13 @@ const Index = ({ data }: { data: Data }) => {
|
||||
.filter(d => d.locale === language)
|
||||
.map(
|
||||
d =>
|
||||
[d.frontmatter.title, new Date(d.frontmatter.date), d.slug] as (
|
||||
| Date
|
||||
| string
|
||||
)[]
|
||||
[d.frontmatter.title, new Date(d.frontmatter.date), d.slug] as [
|
||||
string,
|
||||
Date,
|
||||
string,
|
||||
]
|
||||
)
|
||||
.sort((a, b) => b[1] - a[1]),
|
||||
.sort((a, b) => b[1].getTime() - a[1].getTime()),
|
||||
[data, language]
|
||||
);
|
||||
|
||||
@@ -226,17 +232,24 @@ const Index = ({ data }: { data: Data }) => {
|
||||
<Typography gutterBottom variant="h5" component="div">
|
||||
<Trans>常用镜像</Trans>
|
||||
</Typography>
|
||||
<Grid container spacing={{ xs: 2 }} columns={{ xs: 1, sm: 3, md: 6 }}>
|
||||
<Grid
|
||||
container
|
||||
spacing={{ xs: 2 }}
|
||||
columns={{ xs: 1, sm: 3, md: 6 }}
|
||||
>
|
||||
{frequentlyUsedMirror.map((e, i) => {
|
||||
const mirror = mirrors[e.id];
|
||||
return (
|
||||
mirror && (
|
||||
<Grid item xs={1} key={i}>
|
||||
<FrequentlyUsedMirrorCard
|
||||
name={mirror.name[language]}
|
||||
desc={mirror.desc[language]}
|
||||
name={mirror.name[language as Locale]}
|
||||
desc={mirror.desc[language as Locale]}
|
||||
icon={e.icon}
|
||||
url={getUrl(mirror.docUrl || mirror.url, !!mirror.docUrl)}
|
||||
url={getUrl(
|
||||
mirror.docUrl || mirror.url,
|
||||
!!mirror.docUrl
|
||||
)}
|
||||
/>
|
||||
</Grid>
|
||||
)
|
||||
@@ -249,8 +262,8 @@ const Index = ({ data }: { data: Data }) => {
|
||||
<Trans>近期更新</Trans>
|
||||
</Typography>
|
||||
<Grid>
|
||||
{newsUrls.map(([title, date, url], _) => (
|
||||
<Grid container>
|
||||
{newsUrls.map(([title, date, url], i) => (
|
||||
<Grid container key={i}>
|
||||
<Link href={url} underline="hover">
|
||||
{title}
|
||||
</Link>
|
||||
|
||||
@@ -8,11 +8,12 @@ import TableCell from '@mui/material/TableCell';
|
||||
import TableHead from '@mui/material/TableHead';
|
||||
import TableRow from '@mui/material/TableRow';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { Link } from 'gatsby-theme-material-ui';
|
||||
import React, { memo } from 'react';
|
||||
import { MDXComponents } from '@mdx-js/react/lib';
|
||||
import { LinkLink as Link } from '~/components/link-mui-components';
|
||||
import CodeBlock from '../components/code-block';
|
||||
|
||||
const components = {
|
||||
const components: MDXComponents = {
|
||||
p: (() => {
|
||||
const Paragraph = props => (
|
||||
<Typography {...props} style={{ margin: '8px 0' }} />
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { ArrowBack, ConnectedTvOutlined } from '@mui/icons-material';
|
||||
import FolderIcon from '@mui/icons-material/Folder';
|
||||
import { Box, Grid, Typography } from '@mui/material';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import { graphql } from 'gatsby';
|
||||
import { Trans, useI18next } from 'gatsby-plugin-react-i18next';
|
||||
import { Button } from 'gatsby-theme-material-ui';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { LinkButton as Button } from '~/components/link-mui-components';
|
||||
import React, { PropsWithChildren, useEffect, useState } from 'react';
|
||||
import Footer from '../components/footer';
|
||||
import FileList from '../components/file-list';
|
||||
import LanguageIconButton from '../components/language-icon-button';
|
||||
import Seo from '../components/seo';
|
||||
import StatusIndicator from '../components/status-indicator';
|
||||
import ThemeIconButton from '../components/theme-icon-button';
|
||||
import { MirrorDto } from '../types/mirror';
|
||||
import { Locale, MirrorDto } from '../types/mirror';
|
||||
import { Link } from '../utils/i18n-link';
|
||||
import components from './components';
|
||||
import { readCache, writeCache } from '../utils/cache';
|
||||
import { popCache, writeCache } from '../utils/cache';
|
||||
import { getUrl } from '../utils/url';
|
||||
import TitleMirrorIcon from '../utils/title-mirror-icon';
|
||||
|
||||
@@ -27,6 +25,10 @@ interface Data {
|
||||
};
|
||||
}
|
||||
|
||||
type MirrorDocProps = {
|
||||
data: Data;
|
||||
};
|
||||
|
||||
async function fetchMirror(id: string): Promise<MirrorDto> {
|
||||
const res = await fetch(`/api/mirrors/${id}`);
|
||||
if (!res.ok) {
|
||||
@@ -37,7 +39,7 @@ async function fetchMirror(id: string): Promise<MirrorDto> {
|
||||
return json;
|
||||
}
|
||||
|
||||
const MirrorDoc = ({ data, children }: { data: Data }) => {
|
||||
const MirrorDoc = ({ data, children }: PropsWithChildren<MirrorDocProps>) => {
|
||||
const { language } = useI18next();
|
||||
|
||||
const defaultData = {
|
||||
@@ -48,11 +50,12 @@ const MirrorDoc = ({ data, children }: { data: Data }) => {
|
||||
},
|
||||
status: 'unknown',
|
||||
} as MirrorDto;
|
||||
const mirrorId = data.document.frontmatter.mirrorId;
|
||||
const { mirrorId } = data.document.frontmatter;
|
||||
|
||||
const [mirror, setMirror] = useState<MirrorDto>(
|
||||
readCache(`mirrors_${mirrorId}`, defaultData)
|
||||
);
|
||||
const [mirror, setMirror] = useState<MirrorDto>({
|
||||
...defaultData,
|
||||
...popCache(`mirrors_${mirrorId}`, defaultData),
|
||||
});
|
||||
useEffect(() => {
|
||||
fetchMirror(mirrorId)
|
||||
.then(d => setMirror(d))
|
||||
@@ -62,7 +65,7 @@ const MirrorDoc = ({ data, children }: { data: Data }) => {
|
||||
const fallbackUrl = `/${mirrorId}`;
|
||||
const mirrorUrl = getUrl(mirror.url ?? fallbackUrl, false);
|
||||
|
||||
const name = mirror.name[language];
|
||||
const name = mirror.name[language as Locale];
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
@@ -90,11 +93,9 @@ const MirrorDoc = ({ data, children }: { data: Data }) => {
|
||||
</Typography>
|
||||
</Link>
|
||||
<Grid item>
|
||||
{
|
||||
/* TODO: add English docs
|
||||
{/* TODO: add English docs
|
||||
<LanguageIconButton />
|
||||
*/
|
||||
}
|
||||
*/}
|
||||
<ThemeIconButton />
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
import { MDXProvider } from '@mdx-js/react';
|
||||
import { ArrowBack, DateRange, AccountCircle } from '@mui/icons-material';
|
||||
import FolderIcon from '@mui/icons-material/Folder';
|
||||
import { DateRange, AccountCircle } from '@mui/icons-material';
|
||||
import { Box, Grid, Typography } from '@mui/material';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import { graphql } from 'gatsby';
|
||||
import { Trans, useI18next } from 'gatsby-plugin-react-i18next';
|
||||
import { Button } from 'gatsby-theme-material-ui';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React from 'react';
|
||||
import Footer from '../components/footer';
|
||||
import FileList from '../components/file-list';
|
||||
import LanguageIconButton from '../components/language-icon-button';
|
||||
import Seo from '../components/seo';
|
||||
import StatusIndicator from '../components/status-indicator';
|
||||
import ThemeIconButton from '../components/theme-icon-button';
|
||||
import { NewsDto } from '../types/news';
|
||||
import { Link } from '../utils/i18n-link';
|
||||
import components from './components';
|
||||
import { readCache, writeCache } from '../utils/cache';
|
||||
import { getUrl } from '../utils/url';
|
||||
|
||||
interface Data {
|
||||
document: {
|
||||
|
||||
@@ -20,9 +20,9 @@ export interface MirrorDto {
|
||||
name: Record<Locale, string>;
|
||||
desc: Record<Locale, string>;
|
||||
status: MirrorStatus;
|
||||
lastUpdated: string;
|
||||
nextScheduled: string;
|
||||
lastSuccess: string;
|
||||
lastUpdated: number;
|
||||
nextScheduled: number;
|
||||
lastSuccess: number;
|
||||
url: string;
|
||||
files?: File[];
|
||||
}
|
||||
|
||||
@@ -11,4 +11,10 @@ function readCache<T>(key: string, defaultValue: T): T {
|
||||
return d ? JSON.parse(d) : defaultValue;
|
||||
}
|
||||
|
||||
export { writeCache, readCache };
|
||||
function popCache<T>(key: string, defaultValue: T): T {
|
||||
const d = readCache(key, defaultValue);
|
||||
localStorage.removeItem(`${cachePrefix}${key}`);
|
||||
return d;
|
||||
}
|
||||
|
||||
export { writeCache, readCache, popCache };
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import { useI18next } from 'gatsby-plugin-react-i18next';
|
||||
import { LANGUAGE_KEY } from 'gatsby-plugin-react-i18next/dist/types';
|
||||
import { Link as MuiLink } from 'gatsby-theme-material-ui';
|
||||
import { LinkProps } from '@mui/material';
|
||||
import { LinkLink as MuiLink } from '~/components/link-mui-components';
|
||||
|
||||
export function linkWithI18n<
|
||||
P extends { to: string; onClick?: React.MouseEventHandler }
|
||||
|
||||
19
src/utils/root-layout.tsx
Normal file
19
src/utils/root-layout.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import React from "react";
|
||||
import { ThemeProvider } from "../components/theme-context";
|
||||
import { CssBaseline } from "@mui/material";
|
||||
import { PrefsProvider } from "../components/preferences-context";
|
||||
|
||||
export default function RootLayout({ children } : {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<React.StrictMode>
|
||||
<PrefsProvider>
|
||||
<ThemeProvider>
|
||||
<CssBaseline />
|
||||
{children}
|
||||
</ThemeProvider>
|
||||
</PrefsProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
||||
@@ -29,7 +29,10 @@
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
"paths": { /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
"~/*": ["./src/*"]
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
},
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
|
||||
Reference in New Issue
Block a user