diff --git a/.eslintprettier.config.js b/.eslintprettier.config.js deleted file mode 100644 index ccee73a..0000000 --- a/.eslintprettier.config.js +++ /dev/null @@ -1,14 +0,0 @@ -import prettierPlugin from 'eslint-plugin-prettier' -import eslintConfig from './eslint.config.mjs' - -export default [ - ...eslintConfig, - { - plugins: { - prettier: prettierPlugin, - }, - rules: { - 'prettier/prettier': 'error', - }, - }, -] diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 9e17846..0000000 --- a/.eslintrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "root": true, - "extends": ["@nuxt/eslint-config"] -} diff --git a/.eslintrc.prettier.js b/.eslintrc.prettier.js deleted file mode 100644 index 7a440c2..0000000 --- a/.eslintrc.prettier.js +++ /dev/null @@ -1,24 +0,0 @@ -module.exports = { - root: true, - extends: ['@nuxt/eslint-config', 'plugin:prettier/recommended'], - rules: { - 'prettier/prettier': 'error', - '@stylistic/quotes': ['error', 'single'], - '@stylistic/semi': ['error', 'never'], - '@stylistic/comma-dangle': ['error', 'always-multiline'], - '@stylistic/operator-linebreak': ['error', 'before'], - '@stylistic/member-delimiter-style': [ - 'error', - { - multiline: { - delimiter: 'none', - requireLast: false, - }, - singleline: { - delimiter: 'comma', - requireLast: false, - }, - }, - ], - }, -} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c13139c..9a1674d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,6 +48,9 @@ jobs: - run: pnpm lint --max-warnings 0 + - name: Check formatting + run: pnpm format:check + - name: Prepare module types run: pnpm dev:prepare diff --git a/.prettierignore b/.prettierignore index e688f5c..8eb09df 100644 --- a/.prettierignore +++ b/.prettierignore @@ -19,4 +19,7 @@ coverage .vscode # git -.git \ No newline at end of file +.git + +# pnpm writes the lockfile in its own format +pnpm-lock.yaml diff --git a/README.md b/README.md index ab62939..e5fb38c 100644 --- a/README.md +++ b/README.md @@ -251,6 +251,7 @@ pnpm install --frozen-lockfile pnpm dev:prepare pnpm playwright-core install chromium pnpm lint +pnpm format:check pnpm test:types pnpm test pnpm test:package diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index acc1b73..e638971 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -16,4 +16,4 @@ Contact any of our current maintainers, or send us an email at [community@stackb Use the pnpm version pinned in `package.json`. With Corepack installed, run `corepack enable`, then `pnpm install --frozen-lockfile` and `pnpm dev:prepare` from the repository root. The module and playground share `pnpm-lock.yaml`; install dependencies from the root and use `pnpm --dir playground build` to build the playground directly. -Before submitting a change, run `pnpm lint`, `pnpm test:types`, `pnpm test`, and `pnpm test:package`. For runtime changes, also run `pnpm test:compatibility` and `NUXT_VERSION=3 pnpm test:compatibility` to test independent static-site consumers. +Before submitting a change, run `pnpm lint`, `pnpm format:check`, `pnpm test:types`, `pnpm test`, and `pnpm test:package`. Prettier owns formatting and ESLint checks everything else; `pnpm format` applies the formatting. For runtime changes, also run `pnpm test:compatibility` and `NUXT_VERSION=3 pnpm test:compatibility` to test independent static-site consumers. diff --git a/eslint.config.mjs b/eslint.config.mjs index 4f44f47..dedcb05 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,38 +1,20 @@ // @ts-check import { createConfigForNuxt } from '@nuxt/eslint-config/flat' +import prettier from 'eslint-config-prettier/flat' // Run `npx @eslint/config-inspector` to inspect the resolved config interactively export default createConfigForNuxt({ features: { // Rules for module authors tooling: true, - // Rules for formatting - stylistic: true, + // Prettier formats the code, so the key order rule that came with stylistic is enabled on its own + nuxt: { sortConfigKeys: true }, }, dirs: { src: ['./playground'], }, -}).append({ - rules: { - '@stylistic/quotes': ['error', 'single', { avoidEscape: true }], - '@stylistic/semi': ['error', 'never'], - '@stylistic/comma-dangle': ['error', 'always-multiline'], - '@stylistic/arrow-parens': ['error', 'always'], - '@stylistic/operator-linebreak': 'off', - '@stylistic/brace-style': 'off', - '@stylistic/indent-binary-ops': 'off', - '@stylistic/member-delimiter-style': [ - 'error', - { - multiline: { - delimiter: 'none', - requireLast: false, - }, - singleline: { - delimiter: 'comma', - requireLast: false, - }, - }, - ], - }, +}).append(prettier, { + // eslint-config-prettier turns this off, but without semicolons it is the rule that catches + // a new line silently continuing the previous statement + rules: { 'no-unexpected-multiline': 'error' }, }) diff --git a/package.json b/package.json index e2de09a..0ae730c 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,8 @@ "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground", "release:prepare": "pnpm run prepack && changelogen --release --no-tag --no-push --no-github", "lint": "eslint .", - "lint:prettier": "eslint --config .eslintprettier.config.js .", "format": "prettier --write .", + "format:check": "prettier --check .", "lint:fix": "eslint . --fix && prettier --write .", "test": "vitest run", "test:watch": "vitest watch", @@ -71,7 +71,6 @@ "changelogen": "^0.6.1", "eslint": "^10.7.0", "eslint-config-prettier": "^10.1.5", - "eslint-plugin-prettier": "^5.4.0", "hookable": "^6.1.1", "nuxt": "^4.2.1", "playwright": "1.63.0", diff --git a/playground/app.vue b/playground/app.vue index 4b1f42a..2afe9cf 100644 --- a/playground/app.vue +++ b/playground/app.vue @@ -14,28 +14,15 @@

- - - + + +

Custom Hook Testing

- - + +
diff --git a/playground/plugins/page-category.client.ts b/playground/plugins/page-category.client.ts index 7818f9a..212c6fa 100644 --- a/playground/plugins/page-category.client.ts +++ b/playground/plugins/page-category.client.ts @@ -5,7 +5,9 @@ export default defineNuxtPlugin(() => { const utm = useNuxtUTM() utm.onBeforePersist((data) => { - const pageCategory = new URL(data.additionalInfo.landingPageUrl).searchParams.get('page_category') + const pageCategory = new URL(data.additionalInfo.landingPageUrl).searchParams.get( + 'page_category', + ) if (!pageCategory) return data.customParams = { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 800ccd8..323874f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,9 +55,6 @@ importers: eslint-config-prettier: specifier: ^10.1.5 version: 10.1.8(eslint@10.11.0(jiti@2.7.0)(supports-color@10.2.2)) - eslint-plugin-prettier: - specifier: ^5.4.0 - version: 5.5.6(eslint-config-prettier@10.1.8(eslint@10.11.0(jiti@2.7.0)(supports-color@10.2.2)))(eslint@10.11.0(jiti@2.7.0)(supports-color@10.2.2))(prettier@3.9.9) hookable: specifier: ^6.1.1 version: 6.1.2 @@ -876,10 +873,6 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@pkgr/core@0.3.6': - resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==} - engines: {node: ^14.18.0 || >=16.0.0} - '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} @@ -2273,20 +2266,6 @@ packages: peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 - eslint-plugin-prettier@5.5.6: - resolution: {integrity: sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - '@types/eslint': '>=8.0.0' - eslint: '>=8.0.0' - eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0' - prettier: '>=3.0.0' - peerDependenciesMeta: - '@types/eslint': - optional: true - eslint-config-prettier: - optional: true - eslint-plugin-regexp@3.2.0: resolution: {integrity: sha512-4yq47CnLxyfHFKJEo5kvNaiJ0aDtBxSJWk4M2LiamplUXdWxdlzDYqImb/ZVCp+2BqkQjBAmw4Xc07Q8SXVDZg==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} @@ -2413,9 +2392,6 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} @@ -3704,10 +3680,6 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier-linter-helpers@1.0.1: - resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==} - engines: {node: '>=6.0.0'} - prettier@3.9.9: resolution: {integrity: sha512-Z/CJHIkdujO/OtN7nXUii0Rf3VT5SRuhjBA82Xvu2XhBUgX3nhP67T0LHceBdQLex7OOFGTox+Q5Yg8Jk2Qivg==} engines: {node: '>=14'} @@ -4092,10 +4064,6 @@ packages: engines: {node: '>=16'} hasBin: true - synckit@0.11.13: - resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} - engines: {node: ^14.18.0 || >=16.0.0} - tagged-tag@1.0.0: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} @@ -6087,8 +6055,6 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@pkgr/core@0.3.6': {} - '@polka/url@1.0.0-next.29': {} '@poppinss/colors@4.1.6': @@ -7412,15 +7378,6 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-prettier@5.5.6(eslint-config-prettier@10.1.8(eslint@10.11.0(jiti@2.7.0)(supports-color@10.2.2)))(eslint@10.11.0(jiti@2.7.0)(supports-color@10.2.2))(prettier@3.9.9): - dependencies: - eslint: 10.11.0(jiti@2.7.0)(supports-color@10.2.2) - prettier: 3.9.9 - prettier-linter-helpers: 1.0.1 - synckit: 0.11.13 - optionalDependencies: - eslint-config-prettier: 10.1.8(eslint@10.11.0(jiti@2.7.0)(supports-color@10.2.2)) - eslint-plugin-regexp@3.2.0(eslint@10.11.0(jiti@2.7.0)(supports-color@10.2.2)): dependencies: '@eslint-community/eslint-utils': 4.10.1(eslint@10.11.0(jiti@2.7.0)(supports-color@10.2.2)) @@ -7593,8 +7550,6 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-diff@1.3.0: {} - fast-fifo@1.3.2: {} fast-glob@3.3.3: @@ -9301,10 +9256,6 @@ snapshots: prelude-ls@1.2.1: {} - prettier-linter-helpers@1.0.1: - dependencies: - fast-diff: 1.3.0 - prettier@3.9.9: {} pretty-bytes@7.1.3: {} @@ -9710,10 +9661,6 @@ snapshots: picocolors: 1.1.1 sax: 1.6.1 - synckit@0.11.13: - dependencies: - '@pkgr/core': 0.3.6 - tagged-tag@1.0.0: {} tar-stream@3.2.1: diff --git a/scripts/test-compatibility.mjs b/scripts/test-compatibility.mjs index cafb411..1f89ce7 100644 --- a/scripts/test-compatibility.mjs +++ b/scripts/test-compatibility.mjs @@ -24,8 +24,8 @@ export async function testCompatibility({ root, directory, tarball }) { private: true, type: 'module', packageManager, - dependencies: { 'nuxt': version, 'nuxt-utm': `file:${tarball}`, 'vue': '^3.5.0' }, - devDependencies: { 'typescript': '~5.9.3', 'vue-tsc': '^3.3.8' }, + dependencies: { nuxt: version, 'nuxt-utm': `file:${tarball}`, vue: '^3.5.0' }, + devDependencies: { typescript: '~5.9.3', 'vue-tsc': '^3.3.8' }, }), ) writeFileSync( @@ -39,9 +39,12 @@ export async function testCompatibility({ root, directory, tarball }) { timeout: 300_000, env: { ...process.env, NUXT_TELEMETRY_DISABLED: '1' }, }) - const allowBuilds = JSON.parse(execFileSync(pnpmCommand, [...pnpmArguments, 'config', 'get', 'allowBuilds', '--json'], { - cwd: root, encoding: 'utf8', - })) + const allowBuilds = JSON.parse( + execFileSync(pnpmCommand, [...pnpmArguments, 'config', 'get', 'allowBuilds', '--json'], { + cwd: root, + encoding: 'utf8', + }), + ) writeFileSync(join(fixture, 'pnpm-workspace.yaml'), JSON.stringify({ allowBuilds })) run(['install', '--no-frozen-lockfile']) const installed = JSON.parse( @@ -108,7 +111,13 @@ export async function testCompatibility({ root, directory, tarball }) { await page.getByRole('button', { name: 'Send', exact: true }).click() await page.getByRole('status').filter({ hasText: 'Please try again' }).waitFor() assert.equal(submissions.length, 1) - assert.equal(await page.getByTestId('history-count').textContent().then((text) => text.trim()), '3') + assert.equal( + await page + .getByTestId('history-count') + .textContent() + .then((text) => text.trim()), + '3', + ) await page.getByRole('button', { name: 'Send', exact: true }).click() await page.getByRole('status').filter({ hasText: 'Sent' }).waitFor() assert.equal(submissions.length, 2) diff --git a/test/integration-runtime-control.test.ts b/test/integration-runtime-control.test.ts index bdad6b7..3017c15 100644 --- a/test/integration-runtime-control.test.ts +++ b/test/integration-runtime-control.test.ts @@ -73,7 +73,9 @@ describe('Runtime tracking control', async () => { let rawData = await page.evaluate(() => window.localStorage.getItem('nuxt-utm-data')) let entries = JSON.parse(rawData ?? '[]') - const hasDisabled = entries.some((e: DataObject) => e.utmParams?.utm_source === 'while_disabled') + const hasDisabled = entries.some( + (e: DataObject) => e.utmParams?.utm_source === 'while_disabled', + ) expect(hasDisabled).toBe(false) // Enable tracking @@ -119,7 +121,9 @@ describe('Runtime tracking control', async () => { expect(rawData).toBeNull() // Check session ID is also cleared - const sessionId = await page.evaluate(() => window.sessionStorage.getItem('nuxt-utm-session-id')) + const sessionId = await page.evaluate(() => + window.sessionStorage.getItem('nuxt-utm-session-id'), + ) expect(sessionId).toBeNull() await page.close() diff --git a/test/package-fixture/app/pages/contact.vue b/test/package-fixture/app/pages/contact.vue index b3215ea..674af1a 100644 --- a/test/package-fixture/app/pages/contact.vue +++ b/test/package-fixture/app/pages/contact.vue @@ -40,19 +40,8 @@ async function submitLead() {
- - + +

{{ status }}