diff --git a/.eslintignore b/.eslintignore index c2d3e8400..28768c1b9 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,8 +1,9 @@ -**/*.js -**/*.ts -!packages/astro/**/*.js -!packages/astro/**/*.ts -packages/astro/test/**/*.js +**/*.d.ts +packages/**/dist/**/* +packages/**/fixtures/**/* +packages/webapi/**/* packages/astro/vendor/vite/**/* +examples/**/* +scripts/**/* .github .changeset diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d2d00d081..6cba70e1a 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,7 +1,7 @@ module.exports = { parser: '@typescript-eslint/parser', extends: ['plugin:@typescript-eslint/recommended', 'prettier'], - plugins: ['@typescript-eslint', 'prettier'], + plugins: ['@typescript-eslint', 'prettier', 'no-only-tests'], rules: { '@typescript-eslint/ban-ts-comment': 'off', '@typescript-eslint/camelcase': 'off', @@ -17,5 +17,6 @@ module.exports = { 'prefer-const': 'off', 'no-shadow': 'off', '@typescript-eslint/no-shadow': ['error'], + 'no-only-tests/no-only-tests': 'error' }, }; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 16791b110..df472da10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,9 +54,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: eslint: true - eslint_args: --ignore-pattern test --ignore-pattern vendor - eslint_dir: packages/astro - eslint_extensions: ts prettier: false auto_fix: true git_name: github-actions[bot] diff --git a/package.json b/package.json index 3be9d8e87..fa8f13392 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "test:e2e": "cd packages/astro && pnpm playwright install && pnpm run test:e2e", "test:e2e:match": "cd packages/astro && pnpm playwright install && pnpm run test:e2e:match", "benchmark": "turbo run benchmark --scope=astro", - "lint": "eslint \"packages/**/*.ts\"", + "lint": "eslint .", "version": "changeset version && pnpm install --no-frozen-lockfile && pnpm run format" }, "workspaces": [ @@ -69,6 +69,7 @@ "esbuild": "^0.14.42", "eslint": "^8.16.0", "eslint-config-prettier": "^8.5.0", + "eslint-plugin-no-only-tests": "^2.6.0", "eslint-plugin-prettier": "^4.0.0", "execa": "^6.1.0", "organize-imports-cli": "^0.10.0", diff --git a/packages/astro/e2e/ts-resolution.test.js b/packages/astro/e2e/ts-resolution.test.js index b1d1fcef6..b8d8cf9f9 100644 --- a/packages/astro/e2e/ts-resolution.test.js +++ b/packages/astro/e2e/ts-resolution.test.js @@ -8,8 +8,8 @@ const test = base.extend({ }, }); -function runTest(test) { - test('client:idle', async ({ page, astro }) => { +function runTest(it) { + it('client:idle', async ({ page, astro }) => { await page.goto(astro.resolveUrl('/')); const counter = page.locator('#client-idle'); diff --git a/packages/astro/test/astro-css-bundling.test.js b/packages/astro/test/astro-css-bundling.test.js index 3170b796d..1c470c0ef 100644 --- a/packages/astro/test/astro-css-bundling.test.js +++ b/packages/astro/test/astro-css-bundling.test.js @@ -52,8 +52,8 @@ describe('CSS Bundling', function () { // test 3: assert all bundled CSS was built and contains CSS for (const url of builtCSS.keys()) { - const css = await fixture.readFile(url); - expect(css).to.be.ok; + const bundledCss = await fixture.readFile(url); + expect(bundledCss).to.be.ok; } } }); diff --git a/packages/astro/test/sass.test.js b/packages/astro/test/sass.test.js index 4072d5547..07c1f1499 100644 --- a/packages/astro/test/sass.test.js +++ b/packages/astro/test/sass.test.js @@ -20,7 +20,7 @@ describe('Sass', () => { // TODO: Sass cannot be found on macOS for some reason... Vite issue? const test = os.platform() === 'darwin' ? it.skip : it; test('shows helpful error on failure', async () => { - const res = await fixture.fetch('/error').then((res) => res.text()); - expect(res).to.include('Undefined variable'); + const text = await fixture.fetch('/error').then((res) => res.text()); + expect(text).to.include('Undefined variable'); }); }); diff --git a/packages/astro/test/ssr-adapter-build-config.test.js b/packages/astro/test/ssr-adapter-build-config.test.js index bb1c4514a..37c6ec923 100644 --- a/packages/astro/test/ssr-adapter-build-config.test.js +++ b/packages/astro/test/ssr-adapter-build-config.test.js @@ -26,8 +26,8 @@ describe('Integration buildConfig hook', () => { if (id === '@my-ssr') { return id; } else if (id === 'astro/app') { - const id = viteID(new URL('../dist/core/app/index.js', import.meta.url)); - return id; + const viteId = viteID(new URL('../dist/core/app/index.js', import.meta.url)); + return viteId; } }, load(id) { diff --git a/packages/astro/test/static-build-page-dist-url.test.js b/packages/astro/test/static-build-page-dist-url.test.js index 59adbc57c..cf9839926 100644 --- a/packages/astro/test/static-build-page-dist-url.test.js +++ b/packages/astro/test/static-build-page-dist-url.test.js @@ -2,11 +2,10 @@ import { expect } from 'chai'; import { loadFixture } from './test-utils.js'; describe('Static build: pages routes have distURL', () => { - /** @type {import('./test-utils').Fixture} */ - let fixture; /** @type {RouteData[]} */ let checkRoutes; before(async () => { + /** @type {import('./test-utils').Fixture} */ const fixture = await loadFixture({ root: './fixtures/astro pages/', integrations: [ diff --git a/packages/astro/test/tailwindcss.test.js b/packages/astro/test/tailwindcss.test.js index 15723c456..7a59aebe5 100644 --- a/packages/astro/test/tailwindcss.test.js +++ b/packages/astro/test/tailwindcss.test.js @@ -2,8 +2,6 @@ import { expect } from 'chai'; import * as cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - describe('Tailwind', () => { let fixture; @@ -62,10 +60,10 @@ describe('Tailwind', () => { it('handles Markdown pages', async () => { const html = await fixture.readFile('/markdown-page/index.html'); - const $ = cheerio.load(html); - const bundledCSSHREF = $('link[rel=stylesheet][href^=/assets/]').attr('href'); - const bundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/')); - expect(bundledCSS, 'includes used component classes').to.match(/\.bg-purple-600{/); + const $md = cheerio.load(html); + const bundledCSSHREF = $md('link[rel=stylesheet][href^=/assets/]').attr('href'); + const mdBundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/')); + expect(mdBundledCSS, 'includes used component classes').to.match(/\.bg-purple-600{/); }); }); }); diff --git a/packages/astro/test/test-adapter.js b/packages/astro/test/test-adapter.js index 99ab34e5d..0ed8014ce 100644 --- a/packages/astro/test/test-adapter.js +++ b/packages/astro/test/test-adapter.js @@ -17,8 +17,8 @@ export default function () { if (id === '@my-ssr') { return id; } else if (id === 'astro/app') { - const id = viteID(new URL('../dist/core/app/index.js', import.meta.url)); - return id; + const viteId = viteID(new URL('../dist/core/app/index.js', import.meta.url)); + return viteId; } }, load(id) { diff --git a/packages/create-astro/src/index.ts b/packages/create-astro/src/index.ts index 4fb6cec28..08396a4e8 100644 --- a/packages/create-astro/src/index.ts +++ b/packages/create-astro/src/index.ts @@ -1,3 +1,4 @@ +/* eslint no-console: 'off' */ import degit from 'degit'; import { execa, execaCommand } from 'execa'; import fs from 'fs'; diff --git a/packages/create-astro/test/directory-step.test.js b/packages/create-astro/test/directory-step.test.js index 7193fe298..7c629598a 100644 --- a/packages/create-astro/test/directory-step.test.js +++ b/packages/create-astro/test/directory-step.test.js @@ -1,4 +1,4 @@ -import { resolve } from 'path'; +import path from 'path'; import { promises, existsSync } from 'fs'; import { PROMPT_MESSAGES, testDir, setup, promiseWithTimeout, timeout } from './utils.js'; @@ -31,7 +31,7 @@ describe('[create-astro] select directory', function () { }); }); it('should proceed on an empty directory', async function () { - const resolvedEmptyDirPath = resolve(testDir, inputs.emptyDir); + const resolvedEmptyDirPath = path.resolve(testDir, inputs.emptyDir); if (!existsSync(resolvedEmptyDirPath)) { await promises.mkdir(resolvedEmptyDirPath); } diff --git a/packages/integrations/deno/src/server.ts b/packages/integrations/deno/src/server.ts index eb83c8eae..9d2fc98a9 100644 --- a/packages/integrations/deno/src/server.ts +++ b/packages/integrations/deno/src/server.ts @@ -45,6 +45,7 @@ export function start(manifest: SSRManifest, options: Options) { }); _startPromise = Promise.resolve(_server.listenAndServe()); + // eslint-disable-next-line no-console console.error(`Server running on port ${port}`); } diff --git a/packages/integrations/netlify/test/edge-functions/dynamic-import.test.js b/packages/integrations/netlify/test/edge-functions/dynamic-import.test.js index 2a261b7f6..82961ab8b 100644 --- a/packages/integrations/netlify/test/edge-functions/dynamic-import.test.js +++ b/packages/integrations/netlify/test/edge-functions/dynamic-import.test.js @@ -20,6 +20,7 @@ Deno.test({ const div = doc.querySelector('#thing'); assert(div, 'div exists'); } catch (err) { + // eslint-disable-next-line no-console console.error(err); } finally { await close(); diff --git a/packages/integrations/partytown/src/sirv.ts b/packages/integrations/partytown/src/sirv.ts index aab0c7d96..fa9f9ad25 100644 --- a/packages/integrations/partytown/src/sirv.ts +++ b/packages/integrations/partytown/src/sirv.ts @@ -200,7 +200,7 @@ export default function (dir, opts = {}) { }); } - let lookup = opts.dev ? viaLocal.bind(0, dir, isEtag) : viaCache.bind(0, FILES); + let fileLookup = opts.dev ? viaLocal.bind(0, dir, isEtag) : viaCache.bind(0, FILES); return function (req, res, next) { let extns = ['']; @@ -224,7 +224,7 @@ export default function (dir, opts = {}) { } let data = - lookup(pathname, extns) || (isSPA && !isMatch(pathname, ignores) && lookup(fallback, extns)); + fileLookup(pathname, extns) || (isSPA && !isMatch(pathname, ignores) && fileLookup(fallback, extns)); if (!data) return next ? next() : isNotFound(req, res); if (isEtag && req.headers['if-none-match'] === data.headers['ETag']) { diff --git a/packages/integrations/sitemap/src/utils/logger.ts b/packages/integrations/sitemap/src/utils/logger.ts index 203baeaa7..3292bbdfc 100644 --- a/packages/integrations/sitemap/src/utils/logger.ts +++ b/packages/integrations/sitemap/src/utils/logger.ts @@ -23,7 +23,7 @@ export class Logger implements ILogger { this.packageName = packageName; } - private log(msg: string, prefix: string = '') { + private log(msg: string, prefix = '') { // eslint-disable-next-line no-console console.log(`%s${this.packageName}:%s ${msg}\n`, prefix, prefix ? this.colors.reset : ''); } diff --git a/packages/integrations/sitemap/src/validate-options.ts b/packages/integrations/sitemap/src/validate-options.ts index e4b458003..f51750ff5 100644 --- a/packages/integrations/sitemap/src/validate-options.ts +++ b/packages/integrations/sitemap/src/validate-options.ts @@ -10,7 +10,7 @@ export const validateOptions = (site: string | undefined, opts: SitemapOptions) site: z.string().optional(), // Astro takes care of `site`: how to validate, transform and refine canonicalURL: z.string().optional(), // `canonicalURL` is already validated in prev step }) - .refine(({ site, canonicalURL }) => site || canonicalURL, { + .refine((options) => options.site || options.canonicalURL, { message: 'Required `site` astro.config option or `canonicalURL` integration option', }) .parse({ diff --git a/packages/integrations/vercel/src/lib/fs.ts b/packages/integrations/vercel/src/lib/fs.ts index e192ba554..d7a833cd0 100644 --- a/packages/integrations/vercel/src/lib/fs.ts +++ b/packages/integrations/vercel/src/lib/fs.ts @@ -1,7 +1,7 @@ import type { PathLike } from 'node:fs'; import * as fs from 'node:fs/promises'; -export async function writeJson(path: PathLike, data: T) { +export async function writeJson(path: PathLike, data: T) { await fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); } diff --git a/packages/markdown/remark/src/index.ts b/packages/markdown/remark/src/index.ts index 7034564c3..567a4414d 100644 --- a/packages/markdown/remark/src/index.ts +++ b/packages/markdown/remark/src/index.ts @@ -57,8 +57,8 @@ export async function renderMarkdown( const loadedRemarkPlugins = await Promise.all(loadPlugins(remarkPlugins)); const loadedRehypePlugins = await Promise.all(loadPlugins(rehypePlugins)); - loadedRemarkPlugins.forEach(([plugin, opts]) => { - parser.use([[plugin, opts]]); + loadedRemarkPlugins.forEach(([plugin, pluginOpts]) => { + parser.use([[plugin, pluginOpts]]); }); if (scopedClassName) { @@ -87,8 +87,8 @@ export async function renderMarkdown( ], ]); - loadedRehypePlugins.forEach(([plugin, opts]) => { - parser.use([[plugin, opts]]); + loadedRehypePlugins.forEach(([plugin, pluginOpts]) => { + parser.use([[plugin, pluginOpts]]); }); parser @@ -106,6 +106,7 @@ export async function renderMarkdown( // Ensure that the error message contains the input filename // to make it easier for the user to fix the issue err = prefixError(err, `Failed to parse Markdown file "${input.path}"`); + // eslint-disable-next-line no-console console.error(err); throw err; } diff --git a/packages/markdown/remark/src/rehype-collect-headers.ts b/packages/markdown/remark/src/rehype-collect-headers.ts index 76cb5740c..f8cedd0d5 100644 --- a/packages/markdown/remark/src/rehype-collect-headers.ts +++ b/packages/markdown/remark/src/rehype-collect-headers.ts @@ -20,7 +20,7 @@ export default function createCollectHeaders() { let text = ''; let isJSX = false; - visit(node, (child, _, parent) => { + visit(node, (child, __, parent) => { if (child.type === 'element' || parent == null) { return; } diff --git a/packages/markdown/remark/src/remark-prism.ts b/packages/markdown/remark/src/remark-prism.ts index caa50f738..8f1173af0 100644 --- a/packages/markdown/remark/src/remark-prism.ts +++ b/packages/markdown/remark/src/remark-prism.ts @@ -13,9 +13,9 @@ function runHighlighter(lang: string, code: string) { lang = 'plaintext'; } - const ensureLoaded = (lang: string) => { - if (lang && !Prism.languages[lang]) { - loadLanguages([lang]); + const ensureLoaded = (language: string) => { + if (language && !Prism.languages[language]) { + loadLanguages([language]); } }; @@ -30,6 +30,7 @@ function runHighlighter(lang: string, code: string) { } if (lang && !Prism.languages[lang]) { + // eslint-disable-next-line no-console console.warn(`Unable to load the language: ${lang}`); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 254f0bcb6..accfd82bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,7 @@ importers: esbuild: ^0.14.42 eslint: ^8.16.0 eslint-config-prettier: ^8.5.0 + eslint-plugin-no-only-tests: ^2.6.0 eslint-plugin-prettier: ^4.0.0 execa: ^6.1.0 organize-imports-cli: ^0.10.0 @@ -35,6 +36,7 @@ importers: esbuild: 0.14.43 eslint: 8.17.0 eslint-config-prettier: 8.5.0_eslint@8.17.0 + eslint-plugin-no-only-tests: 2.6.0 eslint-plugin-prettier: 4.0.0_ucegkljdju7q4zmvwxzqoprf3y execa: 6.1.0 organize-imports-cli: 0.10.0 @@ -8248,6 +8250,11 @@ packages: /debug/3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true dependencies: ms: 2.1.3 dev: false @@ -8883,6 +8890,11 @@ packages: eslint: 8.17.0 dev: true + /eslint-plugin-no-only-tests/2.6.0: + resolution: {integrity: sha512-T9SmE/g6UV1uZo1oHAqOvL86XWl7Pl2EpRpnLI8g/bkJu+h7XBCB+1LnubRZ2CUQXj805vh4/CYZdnqtVaEo2Q==} + engines: {node: '>=4.0.0'} + dev: true + /eslint-plugin-prettier/4.0.0_ucegkljdju7q4zmvwxzqoprf3y: resolution: {integrity: sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==} engines: {node: '>=6.0.0'} @@ -11164,6 +11176,8 @@ packages: debug: 3.2.7 iconv-lite: 0.4.24 sax: 1.2.4 + transitivePeerDependencies: + - supports-color dev: false /netmask/2.0.2: @@ -11247,6 +11261,8 @@ packages: rimraf: 2.7.1 semver: 5.7.1 tar: 4.4.19 + transitivePeerDependencies: + - supports-color dev: false /node-releases/2.0.5: