Skip to content

Commit

Permalink
chore: Add ESLint support for MDX files (#1307)
Browse files Browse the repository at this point in the history
# Overview

<!--
    A clear and concise description of what this pr is about.
 -->

related to #1295

I have implemented ESLint linting for MDX files in this project.

### Changes

- Integrate `eslint-plugin-mdx` to enable linting for MDX files
- Apply Prettier rules and JavaScript rules to code blocks within MDX
files
- Update existing MDX files to comply with the new linting rules

This enhancement will improve code consistency and readability across
our MDX documentation.

### Additional Notes

- While [mdx/remark
rules](https://github.com/mdx-js/eslint-mdx?tab=readme-ov-file#rules)
offer potential for more diverse rule sets, they are not implemented in
this PR. This could be explored in future iterations.

- `@eslint/markdown` is designed for `md` files. Since the majority of
Suspensive's documentation uses `MDX`, linting for md files was not
considered in this implementation.

## PR Checklist

- [x] I did below actions if need

1. I read the [Contributing
Guide](https://github.com/toss/suspensive/blob/main/CONTRIBUTING.md)
2. I added documents and tests.

---------

Co-authored-by: Jonghyeon Ko <[email protected]>
Co-authored-by: 김석진(poki) <[email protected]>
Co-authored-by: Gwansik Kim <[email protected]>
  • Loading branch information
4 people authored Oct 12, 2024
1 parent b642880 commit e7dd6ba
Show file tree
Hide file tree
Showing 74 changed files with 1,685 additions and 502 deletions.
7 changes: 6 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{
"recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "antfu.pnpm-catalog-lens"]
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"antfu.pnpm-catalog-lens",
"unifiedjs.vscode-mdx"
]
}
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "mdx"],
"eslint.workingDirectories": [{ "mode": "auto" }],
"vitest.disableWorkspaceWarning": true
}
1 change: 1 addition & 0 deletions configs/eslint-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"eslint-plugin-import": "^2.30.0",
"eslint-plugin-jest-dom": "^5.4.0",
"eslint-plugin-jsdoc": "^50.3.1",
"eslint-plugin-mdx": "^3.1.5",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react-compiler": "0.0.0-experimental-9aef357-20240815",
"eslint-plugin-react-hooks": "^4.6.2",
Expand Down
31 changes: 30 additions & 1 deletion configs/eslint-config/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import cspellConfigs from '@cspell/eslint-plugin/configs'
import vitest from '@vitest/eslint-plugin'
// @ts-expect-error TODO: remove this
import jestDom from 'eslint-plugin-jest-dom'
import mdx from 'eslint-plugin-mdx'

const ignores = ['**/.next/**', '**/build/**', '**/coverage/**', '**/dist/**'] satisfies Linter.Config['ignores']

Expand All @@ -23,9 +24,14 @@ export const suspensiveTypeScriptConfig: ReturnType<typeof tseslint.config> = ts
ignores,
},
cspellConfigs.recommended,
...tseslint.configs.strictTypeChecked,
...tseslint.configs.strictTypeChecked.map((config) => ({
...config,
files: ['**/*.{ts,tsx,js,jsx,cjs,mjs}'],
ignores: ['**/*.mdx/**/*.{ts,tsx,js,jsx,cjs,mjs}'],
})),
{
files: ['**/*.{ts,tsx}'],
ignores: ['**/*.mdx/**/*.{ts,tsx}'],
languageOptions: {
parser: tseslint.parser,
parserOptions: {
Expand Down Expand Up @@ -115,6 +121,7 @@ export const suspensiveReactTypeScriptConfig: ReturnType<typeof tseslint.config>
{
files: ['**/*.{ts,tsx}'],
...(pluginReact.configs.recommended as unknown as ReturnType<typeof tseslint.config>[number]),
ignores: ['**/*.mdx/**/*.{ts,tsx}'],
},
{
plugins: {
Expand All @@ -141,3 +148,25 @@ export const suspensiveNextTypeScriptConfig: ReturnType<typeof tseslint.config>
...suspensiveReactTypeScriptConfig,
{ plugins: { 'plugin:@next/next/recommended': next.configs.recommended } },

Check warning on line 149 in configs/eslint-config/src/index.ts

View workflow job for this annotation

GitHub Actions / Check quality (ci:eslint)

Unsafe assignment of an error typed value

Check warning on line 149 in configs/eslint-config/src/index.ts

View workflow job for this annotation

GitHub Actions / Check quality (ci:eslint)

Unsafe member access .configs on an `error` typed value
]

export const suspensiveMDXConfig: Linter.Config[] = [
mdx.configs.flat,
mdx.configs.flatCodeBlocks,
{
files: ['**/*.mdx'],
...mdx.flat,
processor: mdx.createRemarkProcessor({
lintCodeBlocks: true,
languageMapper: {},
}),
},
{
files: ['**/*.mdx'],
...mdx.flatCodeBlocks,
rules: {
...mdx.flatCodeBlocks.rules,
'no-var': 'error',
'prefer-const': 'error',
},
},
]
7 changes: 6 additions & 1 deletion docs/suspensive.org/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import path from 'path'
import { fileURLToPath } from 'url'
import { suspensiveNextTypeScriptConfig } from '@suspensive/eslint-config'
import {
suspensiveMDXConfig,
suspensiveNextTypeScriptConfig,
} from '@suspensive/eslint-config'

export default [
...suspensiveNextTypeScriptConfig,
...suspensiveMDXConfig,
{
languageOptions: {
parserOptions: {
tsconfigRootDir: path.dirname(fileURLToPath(import.meta.url)),
project: './tsconfig.json',
extraFileExtensions: ['.mdx'],
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion docs/suspensive.org/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"type": "commonjs",
"scripts": {
"build": "next build",
"ci:eslint": "eslint \"**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts}\"",
"ci:eslint": "eslint \"**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts,mdx}\"",
"ci:type": "tsc --noEmit",
"clean": "rimraf ./.next",
"dev": "next dev -p 4000",
Expand Down
1 change: 1 addition & 0 deletions docs/suspensive.org/prettier.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export default {
...rootConfig,
plugins: ['prettier-plugin-tailwindcss'],
tailwindConfig: './tailwind.config.js',
printWidth: 80,
}
6 changes: 5 additions & 1 deletion docs/suspensive.org/src/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ export default function Document() {
return (
<Html lang="ko">
<Head>
<style dangerouslySetInnerHTML={{ __html: getSandpackCssText() }} id="sandpack" key="sandpack-css" />
<style
dangerouslySetInnerHTML={{ __html: getSandpackCssText() }}
id="sandpack"
key="sandpack-css"
/>
</Head>
<body>
<Main />
Expand Down
62 changes: 52 additions & 10 deletions docs/suspensive.org/src/components/BubbleChart.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Suspense } from '@suspensive/react'
import { QueryErrorBoundary, SuspenseQuery, queryOptions } from '@suspensive/react-query-4'
import {
QueryErrorBoundary,
SuspenseQuery,
queryOptions,
} from '@suspensive/react-query-4'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import * as d3 from 'd3'
Expand All @@ -11,7 +15,9 @@ const contributorsQueryOptions = () =>
queryOptions({
queryKey: ['contributors'],
queryFn: () =>
fetch('https://api.github.com/repos/toss/suspensive/stats/contributors').then(async (res) => {
fetch(
'https://api.github.com/repos/toss/suspensive/stats/contributors'
).then(async (res) => {
if (res.ok) {
const data = await res.json()
return data as
Expand Down Expand Up @@ -82,7 +88,12 @@ export const BubbleChart = () => {
{({ data }) => {
const chartData = data
?.filter(
({ author }) => !['github-actions[bot]', 'dependabot[bot]', 'renovate[bot]'].includes(author.login)
({ author }) =>
![
'github-actions[bot]',
'dependabot[bot]',
'renovate[bot]',
].includes(author.login)
)
.map(({ author, total }) => ({
name: author.login,
Expand All @@ -95,16 +106,36 @@ export const BubbleChart = () => {
return (
<>
<div className="flex w-[100%] items-center justify-center overflow-visible sm:hidden md:hidden lg:hidden">
<BubbleChartSize chartData={chartData} height={400} width={400} padding={2} />
<BubbleChartSize
chartData={chartData}
height={400}
width={400}
padding={2}
/>
</div>
<div className="hidden w-[100%] items-center justify-center overflow-visible sm:flex md:hidden lg:hidden">
<BubbleChartSize chartData={chartData} height={630} width={630} padding={6} />
<BubbleChartSize
chartData={chartData}
height={630}
width={630}
padding={6}
/>
</div>
<div className="hidden w-[100%] items-center justify-center overflow-visible sm:hidden md:flex lg:hidden">
<BubbleChartSize chartData={chartData} height={560} width={560} padding={4} />
<BubbleChartSize
chartData={chartData}
height={560}
width={560}
padding={4}
/>
</div>
<div className="hidden w-[100%] items-center justify-center overflow-visible sm:hidden md:hidden lg:flex">
<BubbleChartSize chartData={chartData} height={760} width={760} padding={8} />
<BubbleChartSize
chartData={chartData}
height={760}
width={760}
padding={8}
/>
</div>
</>
)
Expand Down Expand Up @@ -137,7 +168,12 @@ type Node = {
htmlUrl: string
children?: Node[]
}
const BubbleChartSize = (props: { chartData: Array<Node>; width: number; height: number; padding: number }) => {
const BubbleChartSize = (props: {
chartData: Array<Node>
width: number
height: number
padding: number
}) => {
const svgRef = useRef<SVGSVGElement | null>(null)

useEffect(() => {
Expand All @@ -148,7 +184,10 @@ const BubbleChartSize = (props: { chartData: Array<Node>; width: number; height:
.sum((d: Node) => (d.value < 100 ? d.value : 100) + 3)
.sort((a, b) => (b.value ?? 0) - (a.value ?? 0))

const pack = d3.pack().size([props.width, props.height]).padding(props.padding)
const pack = d3
.pack()
.size([props.width, props.height])
.padding(props.padding)

const nodes = pack(root).descendants().slice(1)

Expand Down Expand Up @@ -186,7 +225,10 @@ const BubbleChartSize = (props: { chartData: Array<Node>; width: number; height:
.attr('width', (d) => d.r * 2)
.attr('height', (d) => d.r * 2)
.attr('href', (d: d3.HierarchyCircularNode<Node>) => d.data.avatar)
.attr('clip-path', (d) => `circle(${d.r * 1}px at ${d.r * 1}px ${d.r * 1}px)`)
.attr(
'clip-path',
(d) => `circle(${d.r * 1}px at ${d.r * 1}px ${d.r * 1}px)`
)
}, [props.chartData, props.height, props.width, props.padding])

return <svg ref={svgRef} />
Expand Down
11 changes: 8 additions & 3 deletions docs/suspensive.org/src/components/Callout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { Callout as NextraCallout } from 'nextra/components'
import type { ComponentProps } from 'react'

interface CalloutProps extends Omit<ComponentProps<typeof NextraCallout>, 'type'> {
type: 'deprecated' | 'experimental' | ComponentProps<typeof NextraCallout>['type']
interface CalloutProps
extends Omit<ComponentProps<typeof NextraCallout>, 'type'> {
type:
| 'deprecated'
| 'experimental'
| ComponentProps<typeof NextraCallout>['type']
}

export const Callout = ({ type, ...props }: CalloutProps) => {
const definedType = type === 'deprecated' ? 'error' : type === 'experimental' ? 'warning' : type
const definedType =
type === 'deprecated' ? 'error' : type === 'experimental' ? 'warning' : type

return <NextraCallout {...props} type={definedType} />
}
15 changes: 12 additions & 3 deletions docs/suspensive.org/src/components/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@ export const HomePage = ({
return (
<div className="pb-20">
<div className="flex flex-col items-center justify-center gap-8 pt-11 text-center">
<Image src="/img/logo_background_star.png" alt="Suspensive with star" width={400} height={241} />
<Image
src="/img/logo_background_star.png"
alt="Suspensive with star"
width={400}
height={241}
/>
<div className="flex flex-col items-center gap-4">
<div className="relative text-5xl font-bold">
<span>{title}</span> <span className="absolute text-sm">v{version}</span>
<span>{title}</span>{' '}
<span className="absolute text-sm">v{version}</span>
</div>
<p className="text-3xl">{description}</p>
</div>
Expand All @@ -44,7 +50,10 @@ export const HomePage = ({
<div className="h-14"></div>
<div className="flex flex-col items-start justify-between gap-8 md:flex-row">
{items.map(({ title, desc }) => (
<div className="flex flex-1 flex-col items-center justify-center gap-3 text-center" key={title}>
<div
className="flex flex-1 flex-col items-center justify-center gap-3 text-center"
key={title}
>
<div className="text-xl font-bold">{title}</div>
<p className="text-lg">{desc}</p>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ interface ConsoleCounterButtonProps {
counter: number
}

export const ConsoleCounterButton = ({ onClick, counter }: ConsoleCounterButtonProps) => {
export const ConsoleCounterButton = ({
onClick,
counter,
}: ConsoleCounterButtonProps) => {
return (
<RoundedButton className="relative" onClick={onClick}>
<ConsoleIcon />
Expand Down
Loading

0 comments on commit e7dd6ba

Please sign in to comment.