From d2eeacb25d6aa0d380ebaea3077955ac499c731c Mon Sep 17 00:00:00 2001 From: Seth Falco Date: Sat, 7 Sep 2024 00:43:24 +0100 Subject: [PATCH] chore: setup eslint --- .github/workflows/main.yml | 16 +- docusaurus.config.js | 98 +- eslint.config.mjs | 51 + package.json | 9 +- src/components/HomepageFeatures/index.jsx | 2 +- src/components/PluginParams/index.jsx | 2 +- src/components/PluginUsage/index.jsx | 2 +- src/components/SvgDemo/index.jsx | 6 +- src/components/SvgoPreview/index.jsx | 14 +- src/pages/index.js | 4 +- src/plugins/configure-svgo.js | 16 +- src/theme/DocItem/Layout/index.js | 2 +- src/theme/DocItem/index.js | 4 +- src/theme/Footer/Copyright/index.js | 4 +- src/theme/Footer/Layout/index.js | 4 +- src/theme/Footer/Links/MultiColumn/index.js | 10 +- src/theme/Footer/Links/Simple/index.js | 6 +- src/theme/Footer/Links/index.js | 4 +- src/theme/TOCItems/Tree.js | 10 +- yarn.lock | 1359 ++++++++++++++++++- 20 files changed, 1513 insertions(+), 110 deletions(-) create mode 100644 eslint.config.mjs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 55ec89f..b9bc554 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,8 @@ name: CI +env: + NODE: 20 + on: - 'pull_request' @@ -18,7 +21,18 @@ jobs: path: .svgo - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: ${{ env.NODE }} cache: 'yarn' - run: yarn install --immutable - run: yarn run build + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE }} + cache: 'yarn' + - run: yarn install --immutable + - run: yarn run lint diff --git a/docusaurus.config.js b/docusaurus.config.js index 671f56f..c7b9b4b 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -19,20 +19,20 @@ const { themes } = require('prism-react-renderer'); * @type {Config} */ const config = { - title: "SVGO", - favicon: "img/favicon.ico", - url: "https://svgo.dev", - baseUrl: "/", + title: 'SVGO', + favicon: 'img/favicon.ico', + url: 'https://svgo.dev', + baseUrl: '/', baseUrlIssueBanner: false, - organizationName: "svg", - projectName: "svgo.dev", + organizationName: 'svg', + projectName: 'svgo.dev', trailingSlash: true, - onBrokenLinks: "throw", - onBrokenMarkdownLinks: "throw", + onBrokenLinks: 'throw', + onBrokenMarkdownLinks: 'throw', i18n: { - defaultLocale: "en", + defaultLocale: 'en', locales: [ - "en" + 'en' ], }, markdown: { @@ -72,33 +72,33 @@ const config = { }, plugins: [ [ - "@docusaurus/theme-classic", + '@docusaurus/theme-classic', { - customCss: require.resolve("./src/css/custom.css"), + customCss: require.resolve('./src/css/custom.css'), }, ], [ - "@docusaurus/plugin-content-pages", + '@docusaurus/plugin-content-pages', { - path: "src/pages", - routeBasePath: "/" + path: 'src/pages', + routeBasePath: '/' } ], [ - "@docusaurus/plugin-content-docs", + '@docusaurus/plugin-content-docs', { - path: ".svgo/docs", + path: '.svgo/docs', breadcrumbs: true, - sidebarPath: require.resolve("./sidebars.js"), + sidebarPath: require.resolve('./sidebars.js'), editUrl: ({ docPath }) => `https://github.com/svg/svgo/tree/main/docs/${docPath}`, } ], [ - "@docusaurus/plugin-sitemap", + '@docusaurus/plugin-sitemap', { - filename: "sitemap.xml", + filename: 'sitemap.xml', ignorePatterns: [ - "/.well-known/**" + '/.well-known/**' ], createSitemapItems: async (params) => { const { defaultCreateSitemapItems, ...rest } = params; @@ -108,11 +108,11 @@ const config = { items = items.map((item) => { const pathname = new URL(item.url).pathname; - if (pathname === "/") { + if (pathname === '/') { item.priority = 1; - } else if (pathname === "/search/") { + } else if (pathname === '/search/') { item.priority = 0.1; - item.changefreq = "monthly"; + item.changefreq = 'monthly'; } return item; @@ -122,19 +122,19 @@ const config = { }, } ], - "./src/plugins/prefers-color-scheme.js", - "./src/plugins/configure-svgo.js" + './src/plugins/prefers-color-scheme.js', + './src/plugins/configure-svgo.js' ], themes: [ '@docusaurus/theme-live-codeblock', [ - require.resolve("@easyops-cn/docusaurus-search-local"), + require.resolve('@easyops-cn/docusaurus-search-local'), { indexDocs: true, indexBlog: false, - language: "en", + language: 'en', hashed: true, - searchBarPosition: "right" + searchBarPosition: 'right' } ] ], @@ -146,20 +146,20 @@ const config = { navbar: { items: [ { - type: "docSidebar", - position: "left", - sidebarId: "docsSidebar", - label: "Documentation" + type: 'docSidebar', + position: 'left', + sidebarId: 'docsSidebar', + label: 'Documentation' }, { - href: "https://jakearchibald.github.io/svgomg/", - position: "left", - label: "Playground" + href: 'https://jakearchibald.github.io/svgomg/', + position: 'left', + label: 'Playground' }, { - href: "https://github.com/svg/svgo", - position: "right", - html: ``, + href: 'https://github.com/svg/svgo', + position: 'right', + html: '', className: 'github-shield', 'aria-label': 'GitHub repository' } @@ -172,28 +172,28 @@ const config = { footer: { links: [ { - title: "Community", + title: 'Community', items: [ { - label: "Stack Overflow", - href: "https://stackoverflow.com/questions/tagged/svgo", + label: 'Stack Overflow', + href: 'https://stackoverflow.com/questions/tagged/svgo', }, { - label: "Discord", - href: "https://discord.com/invite/z8jX8NYxrE", + label: 'Discord', + href: 'https://discord.com/invite/z8jX8NYxrE', } ], }, { - title: "More", + title: 'More', items: [ { - label: "GitHub", - href: "https://github.com/svg/svgo", + label: 'GitHub', + href: 'https://github.com/svg/svgo', }, { - label: "Open Collective", - href: "https://opencollective.com/svgo" + label: 'Open Collective', + href: 'https://opencollective.com/svgo' } ] } diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..6ff5b79 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,51 @@ +import globals from 'globals'; +import pluginJs from '@eslint/js'; +import pluginReact from 'eslint-plugin-react'; + +/** + * @typedef {import("eslint").Linter.Config} Config + */ + +/** @type {Config[]} */ +export default [ + { + ignores: [ + '.docusaurus/', + '.svgo/', + '.yarn/', + 'build/', + 'node_modules/', + 'yarn.lock' + ] + }, + { + settings: { + react: { + version: 'detect' + } + }, + }, + { + files: ['**/*.{js,mjs,cjs,jsx}'] + }, + { + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + } + } + }, + pluginJs.configs.recommended, + pluginReact.configs.flat.recommended, + { + rules: { + 'object-curly-spacing': ['error', 'always'], + 'quotes': ['error', 'single'], + 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'], + 'react/jsx-indent-props': ['error', 2], + 'react/jsx-max-props-per-line': ['error', { maximum: { 'single': 9, 'multi': 1 } }], + 'react/prop-types': 'off', + } + } +]; diff --git a/package.json b/package.json index 9e1c821..a8f1d04 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,8 @@ "clear": "docusaurus clear", "serve": "docusaurus serve", "write-translations": "docusaurus write-translations", - "write-heading-ids": "docusaurus write-heading-ids" + "write-heading-ids": "docusaurus write-heading-ids", + "lint": "eslint ." }, "dependencies": { "@docusaurus/core": "^3.3.2", @@ -55,5 +56,11 @@ "react-dom": "^18.3.1", "rehype-stringify": "^10.0.0", "svgo": "^3.3.2" + }, + "devDependencies": { + "@eslint/js": "^9.9.1", + "eslint": "^9.9.1", + "eslint-plugin-react": "^7.35.2", + "globals": "^15.9.0" } } diff --git a/src/components/HomepageFeatures/index.jsx b/src/components/HomepageFeatures/index.jsx index 8211f30..404d769 100644 --- a/src/components/HomepageFeatures/index.jsx +++ b/src/components/HomepageFeatures/index.jsx @@ -46,7 +46,7 @@ function Feature({ Svg, title, description }) {
-
+

{title}

{description}

diff --git a/src/components/PluginParams/index.jsx b/src/components/PluginParams/index.jsx index 524e5e9..8f1db1b 100644 --- a/src/components/PluginParams/index.jsx +++ b/src/components/PluginParams/index.jsx @@ -20,7 +20,7 @@ export default function PluginParams() {
{param.name}
-
+
))} diff --git a/src/components/PluginUsage/index.jsx b/src/components/PluginUsage/index.jsx index efd079f..dacd3e6 100644 --- a/src/components/PluginUsage/index.jsx +++ b/src/components/PluginUsage/index.jsx @@ -25,7 +25,7 @@ export default function PluginUsage() { let paramsTemplate = Object.keys(parameters) .filter((key) => parameters[key] && parameters[key].default !== undefined) .map((param) => ` ${param}: ${JSON.stringify(parameters[param].default)}`) - .join(",\n"); + .join(',\n'); return ( diff --git a/src/components/SvgDemo/index.jsx b/src/components/SvgDemo/index.jsx index 12f4f0b..c0c745e 100644 --- a/src/components/SvgDemo/index.jsx +++ b/src/components/SvgDemo/index.jsx @@ -1,8 +1,8 @@ -import React, { useState } from "react"; -import CodeBlock from "@theme/CodeBlock"; +import React, { useState } from 'react'; +import CodeBlock from '@theme/CodeBlock'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -import styles from "./index.module.css"; +import styles from './index.module.css'; export default function SvgPreview(props) { const [ error, setError ] = useState(false); diff --git a/src/components/SvgoPreview/index.jsx b/src/components/SvgoPreview/index.jsx index 33996d6..5067606 100644 --- a/src/components/SvgoPreview/index.jsx +++ b/src/components/SvgoPreview/index.jsx @@ -1,7 +1,7 @@ -import React from "react"; -import { optimize } from "svgo/dist/svgo.browser.js"; +import React from 'react'; +import { optimize } from 'svgo/dist/svgo.browser.js'; import SvgPreview from '../SvgDemo'; -import styles from "./index.module.css"; +import styles from './index.module.css'; export default function SvgoPreview(props) { const { svg, svgoConfig } = props; @@ -12,10 +12,10 @@ export default function SvgoPreview(props) { const optimizedSize = optimized.length; const profit = 100 - (optimizedSize * 100) / initialSize; - const initialUi = Math.round((initialSize / 1024) * 1000) / 1000 + " KiB" - const optimizedUi = Math.round((optimizedSize / 1024) * 1000) / 1000 + " KiB" - const directionUi = (profit < 0 ? "+" : "-"); - const profitUi = Math.abs(Math.round(profit * 10) / 10) + "%"; + const initialUi = Math.round((initialSize / 1024) * 1000) / 1000 + ' KiB' + const optimizedUi = Math.round((optimizedSize / 1024) * 1000) / 1000 + ' KiB' + const directionUi = (profit < 0 ? '+' : '-'); + const profitUi = Math.abs(Math.round(profit * 10) / 10) + '%'; return ( <> diff --git a/src/pages/index.js b/src/pages/index.js index 42a9c2d..5e148d3 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -9,7 +9,7 @@ import HomepageFeatures from '../../src/components/HomepageFeatures'; import styles from './index.module.css'; import SvgoTrixie from '../vectors/svgo_trixie.svg'; -const INSTALL_COMMAND = "npm i -g svgo"; +const INSTALL_COMMAND = 'npm i -g svgo'; const onClick = async () => { navigator.clipboard.writeText(INSTALL_COMMAND); @@ -18,7 +18,7 @@ const onClick = async () => { function HomepageHeader() { return (
-
+

SVG Optimizer for Node.js and CLI diff --git a/src/plugins/configure-svgo.js b/src/plugins/configure-svgo.js index 9f8044e..6916c46 100644 --- a/src/plugins/configure-svgo.js +++ b/src/plugins/configure-svgo.js @@ -1,4 +1,4 @@ -import path from "path"; +import path from 'path'; /** * Docusaurus uses SVGR internally, which in turn uses SVGO. We need to @@ -11,7 +11,7 @@ import path from "path"; */ function configureSvgo() { return { - name: "configure-svgo", + name: 'configure-svgo', configureWebpack(config) { /** @type {object[]} */ const rules = config.module.rules; @@ -19,7 +19,7 @@ function configureSvgo() { const rule = rules.find((rule) => { /** @type {string|undefined} */ const loader = rule.oneOf?.[0]?.use?.[0]?.loader; - return loader && loader.includes("/@svgr/"); + return loader && loader.includes('/@svgr/'); }); const svgoConfig = rule.oneOf[0].use[0].options.svgoConfig; @@ -36,24 +36,24 @@ function configureSvgo() { } }, { - name: "prefixIds", + name: 'prefixIds', params: { - delim: "", + delim: '', prefix: (_, info) => path.parse(info.path).name } }, { - name: "removeXlink", + name: 'removeXlink', params: { includeLegacy: true } }, - "removeXMLNS" + 'removeXMLNS' ]; return { mergeStrategy: { - "module.rules": "replace" + 'module.rules': 'replace' }, module: { rules } }; diff --git a/src/theme/DocItem/Layout/index.js b/src/theme/DocItem/Layout/index.js index 94ea2d7..271dd17 100644 --- a/src/theme/DocItem/Layout/index.js +++ b/src/theme/DocItem/Layout/index.js @@ -7,7 +7,7 @@ import DocItemContent from '@theme/DocItem/Content'; import DocBreadcrumbs from '@theme/DocBreadcrumbs'; import styles from './styles.module.css'; -export default function DocItemLayout({children}) { +export default function DocItemLayout({ children }) { return (

diff --git a/src/theme/DocItem/index.js b/src/theme/DocItem/index.js index 2732201..72ce290 100644 --- a/src/theme/DocItem/index.js +++ b/src/theme/DocItem/index.js @@ -1,6 +1,6 @@ import React from 'react'; -import {HtmlClassNameProvider} from '@docusaurus/theme-common'; -import {DocProvider} from '@docusaurus/theme-common/internal'; +import { HtmlClassNameProvider } from '@docusaurus/theme-common'; +import { DocProvider } from '@docusaurus/theme-common/internal'; import DocItemMetadata from '@theme/DocItem/Metadata'; import DocItemLayout from '@theme/DocItem/Layout'; diff --git a/src/theme/Footer/Copyright/index.js b/src/theme/Footer/Copyright/index.js index 20df44d..7230c95 100644 --- a/src/theme/Footer/Copyright/index.js +++ b/src/theme/Footer/Copyright/index.js @@ -1,7 +1,7 @@ import React from 'react'; -export default function FooterCopyright({copyright}) { +export default function FooterCopyright({ copyright }) { return ( -
+
); } diff --git a/src/theme/Footer/Layout/index.js b/src/theme/Footer/Layout/index.js index a3dff17..faf736a 100644 --- a/src/theme/Footer/Layout/index.js +++ b/src/theme/Footer/Layout/index.js @@ -13,8 +13,8 @@ export default function FooterLayout({ links, copyright }) { -