fix: housekeeping

This commit is contained in:
Stevan Freeborn
2026-03-26 15:22:04 -05:00
parent e359ca763e
commit d7e82d5a80
14 changed files with 9584 additions and 6404 deletions
+1
View File
@@ -0,0 +1 @@
next-env.d.ts
+44
View File
@@ -0,0 +1,44 @@
import nextPlugin from '@next/eslint-plugin-next';
import prettierPlugin from 'eslint-plugin-prettier';
import prettierConfig from 'eslint-config-prettier';
import tsParser from '@typescript-eslint/parser';
import tsPlugin from '@typescript-eslint/eslint-plugin';
export default [
{
ignores: [
'.next/**',
'node_modules/**',
'coverage/**',
'.swc/**',
],
},
{
files: ['**/*.{js,mjs,cjs,ts,tsx}'],
languageOptions: {
parser: tsParser,
parserOptions: {
ecmaFeatures: {
jsx: true,
},
},
},
plugins: {
'@next/next': nextPlugin,
'@typescript-eslint': tsPlugin,
prettier: prettierPlugin,
},
rules: {
...nextPlugin.configs.recommended.rules,
...nextPlugin.configs['core-web-vitals'].rules,
...tsPlugin.configs.recommended.rules,
'prettier/prettier': [
'error',
{
endOfLine: 'auto',
},
],
},
},
prettierConfig,
];
+3 -2
View File
@@ -1,10 +1,11 @@
import nextJest from 'next/jest';
import type { Config } from 'jest';
import nextJest from 'next/jest.js';
const createJestConfig = nextJest({
dir: './',
});
const config = {
const config: Config = {
testEnvironment: 'jest-environment-jsdom',
clearMocks: true,
collectCoverage: true,
+1 -5
View File
@@ -1,8 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
appDir: true,
},
};
const nextConfig = {};
module.exports = nextConfig;
+9412 -6335
View File
File diff suppressed because it is too large Load Diff
+25 -22
View File
@@ -6,33 +6,36 @@
"dev": "cross-env NODE_OPTIONS='--inspect' next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"lint": "eslint .",
"test": "jest",
"test-coverage": "jest && live-server coverage/"
},
"dependencies": {
"@markdoc/markdoc": "^0.2.2",
"@types/node": "18.15.11",
"@types/react": "18.0.33",
"@types/react-dom": "18.0.11",
"@vercel/analytics": "^1.0.0",
"eslint": "8.38.0",
"eslint-config-next": "13.3.0",
"next": "13.2.4",
"prismjs": "^1.29.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "5.0.4"
"@markdoc/markdoc": "^0.5.7",
"@types/node": "25.5.0",
"@types/react": "19.2.14",
"@types/react-dom": "19.2.3",
"@vercel/analytics": "^2.0.1",
"eslint": "10.1.0",
"eslint-config-next": "16.2.1",
"next": "16.2.1",
"prismjs": "^1.30.0",
"react": "19.2.4",
"react-dom": "19.2.4",
"typescript": "6.0.2"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0",
"@types/prismjs": "^1.26.0",
"cross-env": "^7.0.3",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"prettier": "^2.8.7",
"ts-node": "^10.9.1"
"@eslint/eslintrc": "^3.3.5",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@types/prismjs": "^1.26.6",
"cross-env": "^10.1.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-prettier": "^5.5.5",
"jest": "^30.3.0",
"jest-environment-jsdom": "^30.3.0",
"prettier": "^3.8.1",
"ts-node": "^10.9.2"
}
}
+33 -23
View File
@@ -2,13 +2,24 @@
import React, {
Children,
MouseEvent,
ReactElement,
ReactNode,
useState,
} from 'react';
import styles from './CodeSnippet.module.css';
interface MarkdocFenceProps {
language?: string;
content?: string;
className?: string;
}
function isMarkdocElement(
child: ReactNode
): child is ReactElement<MarkdocFenceProps> {
return React.isValidElement(child);
}
function CodeSnippetCopyButton({
copyText,
}: {
@@ -20,7 +31,7 @@ function CodeSnippetCopyButton({
const [showTooltip, setShowTooltip] =
useState<boolean>(false);
const handleCopy = (e: MouseEvent<HTMLButtonElement>) => {
const handleCopy = () => {
setCopyButtonTooltip(true);
setTimeout(() => {
setCopyButtonTooltip(false);
@@ -129,30 +140,29 @@ export default function CodeSnippet({
setSelectedLanguage(e.target.value);
};
const code = Children.toArray(children)
.filter(
child =>
React.isValidElement(child) &&
child.props.className ===
`language-${selectedLanguage}`
)
.map(child => {
return child as ReactElement;
})[0];
const childrenArray = Children.toArray(children);
const snippetLanguages = Children.toArray(children).map(
child => {
if (React.isValidElement(child)) {
const languageClassParts =
child.props.className.split('-');
if (languageClassParts.length > 1) {
const language = languageClassParts[1];
return language;
}
}
const code = childrenArray.find(
(child): child is ReactElement<MarkdocFenceProps> => {
if (!isMarkdocElement(child)) return false;
const { language, className } = child.props;
return (
language === selectedLanguage ||
className === `language-${selectedLanguage}`
);
}
);
const snippetLanguages = childrenArray
.map(child => {
if (isMarkdocElement(child)) {
const { language, className } = child.props;
return language || className?.split('-')[1];
}
return undefined;
})
.filter((l): l is string => typeof l === 'string');
return (
<div className={styles.snippetContainer}>
<div className={styles.snippetHeader}>
@@ -176,7 +186,7 @@ export default function CodeSnippet({
</>
) : null}
<CodeSnippetCopyButton
copyText={code.props.content}
copyText={code?.props.content ?? ''}
/>
</div>
</div>
+4 -1
View File
@@ -1,3 +1,4 @@
import { ChangeEvent } from 'react';
import { useSectionContext } from '../context/section';
import { Doc, DocsStructure } from '../types/types';
import { toKebabCase } from '../utils/stringUtils';
@@ -9,7 +10,9 @@ export default function SectionDropdown({
version: DocsStructure;
}) {
const { section, setSection } = useSectionContext();
const handleSelectChange = (e: any) => {
const handleSelectChange = (
e: ChangeEvent<HTMLSelectElement>
) => {
setSection(e.target.value);
location.hash = e.target.value;
};
+17 -3
View File
@@ -7,7 +7,14 @@ import {
useState,
} from 'react';
const SectionContext = createContext({});
type SectionContextType = {
section: string;
setSection: (section: string) => void;
};
const SectionContext = createContext<
SectionContextType | undefined
>(undefined);
export const SectionContextProvider = ({
children,
@@ -25,5 +32,12 @@ export const SectionContextProvider = ({
);
};
export const useSectionContext: any = () =>
useContext(SectionContext);
export const useSectionContext = (): SectionContextType => {
const context = useContext(SectionContext);
if (!context) {
throw new Error(
'useSectionContext must be used within SectionContextProvider'
);
}
return context;
};
+17 -3
View File
@@ -7,6 +7,11 @@ import {
useState,
} from 'react';
interface ThemeContextType {
theme: string;
setTheme: (theme: string) => void;
}
const darkTheme = {
color: 'white',
backgroundColor: '#05254a',
@@ -17,7 +22,9 @@ const lightTheme = {
backgroundColor: 'white',
};
const ThemeContext = createContext({});
const ThemeContext = createContext<
ThemeContextType | undefined
>(undefined);
export const ThemeContextProvider = ({
children,
@@ -38,5 +45,12 @@ export const themes = {
light: lightTheme,
} as { [key: string]: { [key: string]: string } };
export const useThemeContext: any = () =>
useContext(ThemeContext);
export const useThemeContext = (): ThemeContextType => {
const context = useContext(ThemeContext);
if (!context) {
throw new Error(
'useThemeContext must be used within ThemeContextProvider'
);
}
return context;
};
+2
View File
@@ -9,6 +9,8 @@ export default function GlobalError({
error: Error;
reset: () => void;
}) {
console.error(error);
return (
<div className={styles.container}>
<h2>Something went wrong!</h2>
+3 -2
View File
@@ -15,11 +15,12 @@ export const metadata = {
},
],
},
viewport: {
};
export const viewport = {
width: 'device-width',
initialScale: 1,
maximumScale: 1,
},
};
export default function RootLayout({
+1 -1
View File
@@ -83,7 +83,7 @@ function parseMarkdown(sourcePath: string): ReactNode {
const ast = Markdoc.parse(source);
const content = Markdoc.transform(
ast,
markDocConfig as any
markDocConfig as never
);
const children = Markdoc.renderers.react(content, React, {
components: {
+21 -7
View File
@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"target": "esnext",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -9,10 +13,10 @@
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"jsx": "react-jsx",
"incremental": true,
"plugins": [
{
@@ -20,9 +24,19 @@
}
],
"paths": {
"@/*": ["./src/*"]
"@/*": [
"./src/*"
]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}