From cbc96ec58ee2a322c46c803d47b9d674c68f2986 Mon Sep 17 00:00:00 2001 From: anko9801 Date: Sun, 29 Dec 2024 13:31:07 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=8E=B8=20feat:=20vue-axe=20=E3=81=A8?= =?UTF-8?q?=20eslint=20plugin=20vuejs=20accesibility=20=E3=81=AE=E5=B0=8E?= =?UTF-8?q?=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eslint.config.js | 11 ++++ package-lock.json | 121 ++++++++++++++++++++++++++++++++++++ package.json | 3 + public/mockServiceWorker.js | 18 +++--- src/env.d.ts | 2 + src/main.ts | 19 +++++- vite.config.ts | 7 ++- 7 files changed, 168 insertions(+), 13 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 2c508982..3931f31f 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,6 +1,7 @@ import pluginJs from '@eslint/js' import eslintConfigPrettier from 'eslint-config-prettier' import pluginVue from 'eslint-plugin-vue' +import pluginVueA11y from 'eslint-plugin-vuejs-accessibility' import globals from 'globals' import tseslint from 'typescript-eslint' @@ -31,5 +32,15 @@ export default [ 'vue/require-default-prop': 'off' } }, + ...pluginVueA11y.configs["flat/recommended"], + { + "rules": { + "vuejs-accessibility/label-has-for": ["error", { + "required": { + "some": ["nesting", "id"] + } + }] + }, + }, eslintConfigPrettier ] diff --git a/package-lock.json b/package-lock.json index 05213a77..fc141be1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,11 +33,13 @@ "@vue/eslint-config-prettier": "^10.1.0", "@vue/eslint-config-typescript": "^14.1.4", "autoprefixer": "^10.4.20", + "axe-core": "^4.10.2", "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.31.0", "eslint-plugin-unused-imports": "^4.1.4", "eslint-plugin-vue": "^9.30.0", + "eslint-plugin-vuejs-accessibility": "^2.4.1", "esno": "^4.8.0", "execa": "^9.5.1", "globals": "^15.12.0", @@ -51,6 +53,7 @@ "typescript": "^5.6.3", "typescript-eslint": "^8.12.2", "vite": "^5.4.10", + "vue-axe": "^3.1.2", "vue-tsc": "^2.1.10" } }, @@ -2617,6 +2620,16 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", @@ -2801,6 +2814,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axe-core": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, "node_modules/axios": { "version": "1.7.8", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz", @@ -4027,6 +4050,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/eslint-plugin-vuejs-accessibility": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-2.4.1.tgz", + "integrity": "sha512-ZRZhPdslplZXSF71MtSG+zXYRAT5KiHR4JVuo/DERQf9noAkDvi5W418VOE1qllmJd7wTenndxi1q8XeDMxdHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.0", + "emoji-regex": "^10.0.0", + "vue-eslint-parser": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-vuejs-accessibility/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true, + "license": "MIT" + }, "node_modules/eslint-scope": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", @@ -6672,6 +6720,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/proxy-agent": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", @@ -8480,6 +8538,23 @@ } } }, + "node_modules/vue-axe": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vue-axe/-/vue-axe-3.1.2.tgz", + "integrity": "sha512-RZbc+u6gGy6ecI3hK/5jTMG3fTNLTaNL5s6arAoXskVb92hAtkHZ+peQbDJl49sS4hevUXR+del6rUOdI0bcYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prismjs": "^1.21.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "axe-core": "^4.0.0", + "vue": "^3.0.0" + } + }, "node_modules/vue-eslint-parser": { "version": "9.4.3", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", @@ -10490,6 +10565,12 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true + }, "array-buffer-byte-length": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", @@ -10605,6 +10686,12 @@ "possible-typed-array-names": "^1.0.0" } }, + "axe-core": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", + "dev": true + }, "axios": { "version": "1.7.8", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz", @@ -11492,6 +11579,25 @@ } } }, + "eslint-plugin-vuejs-accessibility": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-2.4.1.tgz", + "integrity": "sha512-ZRZhPdslplZXSF71MtSG+zXYRAT5KiHR4JVuo/DERQf9noAkDvi5W418VOE1qllmJd7wTenndxi1q8XeDMxdHw==", + "dev": true, + "requires": { + "aria-query": "^5.3.0", + "emoji-regex": "^10.0.0", + "vue-eslint-parser": "^9.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + } + } + }, "eslint-scope": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", @@ -13197,6 +13303,12 @@ "parse-ms": "^4.0.0" } }, + "prismjs": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", + "integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==", + "dev": true + }, "proxy-agent": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz", @@ -14342,6 +14454,15 @@ "@vue/shared": "3.5.13" } }, + "vue-axe": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vue-axe/-/vue-axe-3.1.2.tgz", + "integrity": "sha512-RZbc+u6gGy6ecI3hK/5jTMG3fTNLTaNL5s6arAoXskVb92hAtkHZ+peQbDJl49sS4hevUXR+del6rUOdI0bcYQ==", + "dev": true, + "requires": { + "prismjs": "^1.21.0" + } + }, "vue-eslint-parser": { "version": "9.4.3", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", diff --git a/package.json b/package.json index 0e15b868..d6ad62e3 100644 --- a/package.json +++ b/package.json @@ -40,11 +40,13 @@ "@vue/eslint-config-prettier": "^10.1.0", "@vue/eslint-config-typescript": "^14.1.4", "autoprefixer": "^10.4.20", + "axe-core": "^4.10.2", "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.31.0", "eslint-plugin-unused-imports": "^4.1.4", "eslint-plugin-vue": "^9.30.0", + "eslint-plugin-vuejs-accessibility": "^2.4.1", "esno": "^4.8.0", "execa": "^9.5.1", "globals": "^15.12.0", @@ -58,6 +60,7 @@ "typescript": "^5.6.3", "typescript-eslint": "^8.12.2", "vite": "^5.4.10", + "vue-axe": "^3.1.2", "vue-tsc": "^2.1.10" }, "msw": { diff --git a/public/mockServiceWorker.js b/public/mockServiceWorker.js index 8c13930a..fead0b3f 100644 --- a/public/mockServiceWorker.js +++ b/public/mockServiceWorker.js @@ -8,8 +8,8 @@ * - Please do NOT serve this file on production. */ -const PACKAGE_VERSION = '2.6.1' -const INTEGRITY_CHECKSUM = '07a8241b182f8a246a7cd39894799a9e' +const PACKAGE_VERSION = '2.6.6' +const INTEGRITY_CHECKSUM = 'ca7800994cc8bfb5eb961e037c877074' const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') const activeClientIds = new Set() @@ -192,12 +192,14 @@ async function getResponse(event, client, requestId) { const requestClone = request.clone() function passthrough() { - const headers = Object.fromEntries(requestClone.headers.entries()) - - // Remove internal MSW request header so the passthrough request - // complies with any potential CORS preflight checks on the server. - // Some servers forbid unknown request headers. - delete headers['x-msw-intention'] + // Cast the request headers to a new Headers instance + // so the headers can be manipulated with. + const headers = new Headers(requestClone.headers) + + // Remove the "accept" header value that marked this request as passthrough. + // This prevents request alteration and also keeps it compliant with the + // user-defined CORS policies. + headers.delete('accept', 'msw/passthrough') return fetch(requestClone, { headers }) } diff --git a/src/env.d.ts b/src/env.d.ts index d4bd956b..19487c02 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -8,3 +8,5 @@ declare module '*.vue' { } declare const _APP_VERSION: string + +declare module "vue-axe" diff --git a/src/main.ts b/src/main.ts index adadc43c..515287ee 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,5 @@ import { createPinia } from 'pinia' -import { createApp } from 'vue' +import { Fragment, createApp, h } from 'vue' import type { PluginOptions } from 'vue-toastification' import Toast, { POSITION } from 'vue-toastification' import 'vue-toastification/dist/index.css' @@ -11,7 +11,20 @@ import router from './router' initMock() -const app = createApp(App) +const setup = async () => { + if (import.meta.env.NODE_DEV === 'production') { + return createApp(App) + } + + // NOTE: 開発環境では vue-axe を読み込む + const VueAxe = await import('vue-axe') + const app = createApp({ + render: () => h(Fragment, [h(App), h(VueAxe.VueAxePopup)]) + }) + app.use(VueAxe.default) + + return app +} const options: PluginOptions = { position: POSITION.BOTTOM_LEFT, @@ -22,4 +35,4 @@ const options: PluginOptions = { hideProgressBar: true } -app.use(router).use(createPinia()).use(Toast, options).mount('#app') +setup().then((app) => app.use(router).use(createPinia()).use(Toast, options).mount('#app')) diff --git a/vite.config.ts b/vite.config.ts index fa08c706..70b78c53 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,6 +1,6 @@ -import vue from '@vitejs/plugin-vue' import * as https from 'https' import * as path from 'path' +import vue from '@vitejs/plugin-vue' import brotli from 'rollup-plugin-brotli' import { defineConfig } from 'vite' @@ -23,5 +23,8 @@ export default defineConfig({ agent: keepAliveAgent } } - } + }, + optimizeDeps: { + include: ["axe-core"], + }, }) From 61daf546ae8905498fd89d43701a8c0b96dbc21e Mon Sep 17 00:00:00 2001 From: anko9801 Date: Sun, 29 Dec 2024 13:32:58 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=90=9B=20fix:=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/env.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/env.d.ts b/src/env.d.ts index 19487c02..664b8bdc 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -9,4 +9,4 @@ declare module '*.vue' { declare const _APP_VERSION: string -declare module "vue-axe" +declare module 'vue-axe'