diff --git a/AGENTS.md b/AGENTS.md index 5522d6c..79ecacc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -48,5 +48,7 @@ ## セキュリティ & 設定の注意点 - 環境ファイル: `.env.local`(開発用)、`.env.production`(ビルド用)。秘密情報はコミット禁止。 +- `pnpm build` を行う場合、直前に `.output` ディレクトリを削除すること。もし他のプロセスが掴んでロックされている場合は `taskkill /IM node.exe /F` 後に `Remove-Item -Force .output` で削除する。 +- `pnpm build` もしくは `pnpm preview` を実行しCLIがタイムアウトした場合は処理を中断して状況を報告すること。 - `runtimeConfig` のキー(例: `API_BASE_URL`, `GOOGLE_CLIENT_ID`)は正しく設定すること。 - ローカル HTTPS は `public/` 内の証明書を使用。警告が出たら信頼設定を行うこと。 diff --git a/assets/styles/primeicons.css b/assets/styles/primeicons.css new file mode 100644 index 0000000..768afda --- /dev/null +++ b/assets/styles/primeicons.css @@ -0,0 +1,1329 @@ +@font-face { + font-family: 'primeicons'; + font-display: block; + src: url("/fonts/primeicons.woff2") format("woff2"); + font-weight: normal; + font-style: normal; +} + +.pi { + font-family: 'primeicons'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + display: inline-block; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.pi:before { + --webkit-backface-visibility:hidden; + backface-visibility: hidden; +} + +.pi-fw { + width: 1.28571429em; + text-align: center; +} + +.pi-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} + +@media (prefers-reduced-motion: reduce) { + .pi-spin { + -webkit-animation-delay: -1ms; + animation-delay: -1ms; + -webkit-animation-duration: 1ms; + animation-duration: 1ms; + -webkit-animation-iteration-count: 1; + animation-iteration-count: 1; + -webkit-transition-delay: 0s; + transition-delay: 0s; + -webkit-transition-duration: 0s; + transition-duration: 0s; + } +} + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + +.pi-folder-plus:before { + content: "\ea05"; +} + +.pi-receipt:before { + content: "\ea06"; +} + +.pi-asterisk:before { + content: "\ea07"; +} + +.pi-face-smile:before { + content: "\ea08"; +} + +.pi-pinterest:before { + content: "\ea09"; +} + +.pi-expand:before { + content: "\ea0a"; +} + +.pi-pen-to-square:before { + content: "\ea0b"; +} + +.pi-wave-pulse:before { + content: "\ea0c"; +} + +.pi-turkish-lira:before { + content: "\ea0d"; +} + +.pi-spinner-dotted:before { + content: "\ea0e"; +} + +.pi-crown:before { + content: "\ea0f"; +} + +.pi-pause-circle:before { + content: "\ea10"; +} + +.pi-warehouse:before { + content: "\ea11"; +} + +.pi-objects-column:before { + content: "\ea12"; +} + +.pi-clipboard:before { + content: "\ea13"; +} + +.pi-play-circle:before { + content: "\ea14"; +} + +.pi-venus:before { + content: "\ea15"; +} + +.pi-cart-minus:before { + content: "\ea16"; +} + +.pi-file-plus:before { + content: "\ea17"; +} + +.pi-microchip:before { + content: "\ea18"; +} + +.pi-twitch:before { + content: "\ea19"; +} + +.pi-building-columns:before { + content: "\ea1a"; +} + +.pi-file-check:before { + content: "\ea1b"; +} + +.pi-microchip-ai:before { + content: "\ea1c"; +} + +.pi-trophy:before { + content: "\ea1d"; +} + +.pi-barcode:before { + content: "\ea1e"; +} + +.pi-file-arrow-up:before { + content: "\ea1f"; +} + +.pi-mars:before { + content: "\ea20"; +} + +.pi-tiktok:before { + content: "\ea21"; +} + +.pi-arrow-up-right-and-arrow-down-left-from-center:before { + content: "\ea22"; +} + +.pi-ethereum:before { + content: "\ea23"; +} + +.pi-list-check:before { + content: "\ea24"; +} + +.pi-thumbtack:before { + content: "\ea25"; +} + +.pi-arrow-down-left-and-arrow-up-right-to-center:before { + content: "\ea26"; +} + +.pi-equals:before { + content: "\ea27"; +} + +.pi-lightbulb:before { + content: "\ea28"; +} + +.pi-star-half:before { + content: "\ea29"; +} + +.pi-address-book:before { + content: "\ea2a"; +} + +.pi-chart-scatter:before { + content: "\ea2b"; +} + +.pi-indian-rupee:before { + content: "\ea2c"; +} + +.pi-star-half-fill:before { + content: "\ea2d"; +} + +.pi-cart-arrow-down:before { + content: "\ea2e"; +} + +.pi-calendar-clock:before { + content: "\ea2f"; +} + +.pi-sort-up-fill:before { + content: "\ea30"; +} + +.pi-sparkles:before { + content: "\ea31"; +} + +.pi-bullseye:before { + content: "\ea32"; +} + +.pi-sort-down-fill:before { + content: "\ea33"; +} + +.pi-graduation-cap:before { + content: "\ea34"; +} + +.pi-hammer:before { + content: "\ea35"; +} + +.pi-bell-slash:before { + content: "\ea36"; +} + +.pi-gauge:before { + content: "\ea37"; +} + +.pi-shop:before { + content: "\ea38"; +} + +.pi-headphones:before { + content: "\ea39"; +} + +.pi-eraser:before { + content: "\ea04"; +} + +.pi-stopwatch:before { + content: "\ea01"; +} + +.pi-verified:before { + content: "\ea02"; +} + +.pi-delete-left:before { + content: "\ea03"; +} + +.pi-hourglass:before { + content: "\e9fe"; +} + +.pi-truck:before { + content: "\ea00"; +} + +.pi-wrench:before { + content: "\e9ff"; +} + +.pi-microphone:before { + content: "\e9fa"; +} + +.pi-megaphone:before { + content: "\e9fb"; +} + +.pi-arrow-right-arrow-left:before { + content: "\e9fc"; +} + +.pi-bitcoin:before { + content: "\e9fd"; +} + +.pi-file-edit:before { + content: "\e9f6"; +} + +.pi-language:before { + content: "\e9f7"; +} + +.pi-file-export:before { + content: "\e9f8"; +} + +.pi-file-import:before { + content: "\e9f9"; +} + +.pi-file-word:before { + content: "\e9f1"; +} + +.pi-gift:before { + content: "\e9f2"; +} + +.pi-cart-plus:before { + content: "\e9f3"; +} + +.pi-thumbs-down-fill:before { + content: "\e9f4"; +} + +.pi-thumbs-up-fill:before { + content: "\e9f5"; +} + +.pi-arrows-alt:before { + content: "\e9f0"; +} + +.pi-calculator:before { + content: "\e9ef"; +} + +.pi-sort-alt-slash:before { + content: "\e9ee"; +} + +.pi-arrows-h:before { + content: "\e9ec"; +} + +.pi-arrows-v:before { + content: "\e9ed"; +} + +.pi-pound:before { + content: "\e9eb"; +} + +.pi-prime:before { + content: "\e9ea"; +} + +.pi-chart-pie:before { + content: "\e9e9"; +} + +.pi-reddit:before { + content: "\e9e8"; +} + +.pi-code:before { + content: "\e9e7"; +} + +.pi-sync:before { + content: "\e9e6"; +} + +.pi-shopping-bag:before { + content: "\e9e5"; +} + +.pi-server:before { + content: "\e9e4"; +} + +.pi-database:before { + content: "\e9e3"; +} + +.pi-hashtag:before { + content: "\e9e2"; +} + +.pi-bookmark-fill:before { + content: "\e9df"; +} + +.pi-filter-fill:before { + content: "\e9e0"; +} + +.pi-heart-fill:before { + content: "\e9e1"; +} + +.pi-flag-fill:before { + content: "\e9de"; +} + +.pi-circle:before { + content: "\e9dc"; +} + +.pi-circle-fill:before { + content: "\e9dd"; +} + +.pi-bolt:before { + content: "\e9db"; +} + +.pi-history:before { + content: "\e9da"; +} + +.pi-box:before { + content: "\e9d9"; +} + +.pi-at:before { + content: "\e9d8"; +} + +.pi-arrow-up-right:before { + content: "\e9d4"; +} + +.pi-arrow-up-left:before { + content: "\e9d5"; +} + +.pi-arrow-down-left:before { + content: "\e9d6"; +} + +.pi-arrow-down-right:before { + content: "\e9d7"; +} + +.pi-telegram:before { + content: "\e9d3"; +} + +.pi-stop-circle:before { + content: "\e9d2"; +} + +.pi-stop:before { + content: "\e9d1"; +} + +.pi-whatsapp:before { + content: "\e9d0"; +} + +.pi-building:before { + content: "\e9cf"; +} + +.pi-qrcode:before { + content: "\e9ce"; +} + +.pi-car:before { + content: "\e9cd"; +} + +.pi-instagram:before { + content: "\e9cc"; +} + +.pi-linkedin:before { + content: "\e9cb"; +} + +.pi-send:before { + content: "\e9ca"; +} + +.pi-slack:before { + content: "\e9c9"; +} + +.pi-sun:before { + content: "\e9c8"; +} + +.pi-moon:before { + content: "\e9c7"; +} + +.pi-vimeo:before { + content: "\e9c6"; +} + +.pi-youtube:before { + content: "\e9c5"; +} + +.pi-flag:before { + content: "\e9c4"; +} + +.pi-wallet:before { + content: "\e9c3"; +} + +.pi-map:before { + content: "\e9c2"; +} + +.pi-link:before { + content: "\e9c1"; +} + +.pi-credit-card:before { + content: "\e9bf"; +} + +.pi-discord:before { + content: "\e9c0"; +} + +.pi-percentage:before { + content: "\e9be"; +} + +.pi-euro:before { + content: "\e9bd"; +} + +.pi-book:before { + content: "\e9ba"; +} + +.pi-shield:before { + content: "\e9b9"; +} + +.pi-paypal:before { + content: "\e9bb"; +} + +.pi-amazon:before { + content: "\e9bc"; +} + +.pi-phone:before { + content: "\e9b8"; +} + +.pi-filter-slash:before { + content: "\e9b7"; +} + +.pi-facebook:before { + content: "\e9b4"; +} + +.pi-github:before { + content: "\e9b5"; +} + +.pi-twitter:before { + content: "\e9b6"; +} + +.pi-step-backward-alt:before { + content: "\e9ac"; +} + +.pi-step-forward-alt:before { + content: "\e9ad"; +} + +.pi-forward:before { + content: "\e9ae"; +} + +.pi-backward:before { + content: "\e9af"; +} + +.pi-fast-backward:before { + content: "\e9b0"; +} + +.pi-fast-forward:before { + content: "\e9b1"; +} + +.pi-pause:before { + content: "\e9b2"; +} + +.pi-play:before { + content: "\e9b3"; +} + +.pi-compass:before { + content: "\e9ab"; +} + +.pi-id-card:before { + content: "\e9aa"; +} + +.pi-ticket:before { + content: "\e9a9"; +} + +.pi-file-o:before { + content: "\e9a8"; +} + +.pi-reply:before { + content: "\e9a7"; +} + +.pi-directions-alt:before { + content: "\e9a5"; +} + +.pi-directions:before { + content: "\e9a6"; +} + +.pi-thumbs-up:before { + content: "\e9a3"; +} + +.pi-thumbs-down:before { + content: "\e9a4"; +} + +.pi-sort-numeric-down-alt:before { + content: "\e996"; +} + +.pi-sort-numeric-up-alt:before { + content: "\e997"; +} + +.pi-sort-alpha-down-alt:before { + content: "\e998"; +} + +.pi-sort-alpha-up-alt:before { + content: "\e999"; +} + +.pi-sort-numeric-down:before { + content: "\e99a"; +} + +.pi-sort-numeric-up:before { + content: "\e99b"; +} + +.pi-sort-alpha-down:before { + content: "\e99c"; +} + +.pi-sort-alpha-up:before { + content: "\e99d"; +} + +.pi-sort-alt:before { + content: "\e99e"; +} + +.pi-sort-amount-up:before { + content: "\e99f"; +} + +.pi-sort-amount-down:before { + content: "\e9a0"; +} + +.pi-sort-amount-down-alt:before { + content: "\e9a1"; +} + +.pi-sort-amount-up-alt:before { + content: "\e9a2"; +} + +.pi-palette:before { + content: "\e995"; +} + +.pi-undo:before { + content: "\e994"; +} + +.pi-desktop:before { + content: "\e993"; +} + +.pi-sliders-v:before { + content: "\e991"; +} + +.pi-sliders-h:before { + content: "\e992"; +} + +.pi-search-plus:before { + content: "\e98f"; +} + +.pi-search-minus:before { + content: "\e990"; +} + +.pi-file-excel:before { + content: "\e98e"; +} + +.pi-file-pdf:before { + content: "\e98d"; +} + +.pi-check-square:before { + content: "\e98c"; +} + +.pi-chart-line:before { + content: "\e98b"; +} + +.pi-user-edit:before { + content: "\e98a"; +} + +.pi-exclamation-circle:before { + content: "\e989"; +} + +.pi-android:before { + content: "\e985"; +} + +.pi-google:before { + content: "\e986"; +} + +.pi-apple:before { + content: "\e987"; +} + +.pi-microsoft:before { + content: "\e988"; +} + +.pi-heart:before { + content: "\e984"; +} + +.pi-mobile:before { + content: "\e982"; +} + +.pi-tablet:before { + content: "\e983"; +} + +.pi-key:before { + content: "\e981"; +} + +.pi-shopping-cart:before { + content: "\e980"; +} + +.pi-comments:before { + content: "\e97e"; +} + +.pi-comment:before { + content: "\e97f"; +} + +.pi-briefcase:before { + content: "\e97d"; +} + +.pi-bell:before { + content: "\e97c"; +} + +.pi-paperclip:before { + content: "\e97b"; +} + +.pi-share-alt:before { + content: "\e97a"; +} + +.pi-envelope:before { + content: "\e979"; +} + +.pi-volume-down:before { + content: "\e976"; +} + +.pi-volume-up:before { + content: "\e977"; +} + +.pi-volume-off:before { + content: "\e978"; +} + +.pi-eject:before { + content: "\e975"; +} + +.pi-money-bill:before { + content: "\e974"; +} + +.pi-images:before { + content: "\e973"; +} + +.pi-image:before { + content: "\e972"; +} + +.pi-sign-in:before { + content: "\e970"; +} + +.pi-sign-out:before { + content: "\e971"; +} + +.pi-wifi:before { + content: "\e96f"; +} + +.pi-sitemap:before { + content: "\e96e"; +} + +.pi-chart-bar:before { + content: "\e96d"; +} + +.pi-camera:before { + content: "\e96c"; +} + +.pi-dollar:before { + content: "\e96b"; +} + +.pi-lock-open:before { + content: "\e96a"; +} + +.pi-table:before { + content: "\e969"; +} + +.pi-map-marker:before { + content: "\e968"; +} + +.pi-list:before { + content: "\e967"; +} + +.pi-eye-slash:before { + content: "\e965"; +} + +.pi-eye:before { + content: "\e966"; +} + +.pi-folder-open:before { + content: "\e964"; +} + +.pi-folder:before { + content: "\e963"; +} + +.pi-video:before { + content: "\e962"; +} + +.pi-inbox:before { + content: "\e961"; +} + +.pi-lock:before { + content: "\e95f"; +} + +.pi-unlock:before { + content: "\e960"; +} + +.pi-tags:before { + content: "\e95d"; +} + +.pi-tag:before { + content: "\e95e"; +} + +.pi-power-off:before { + content: "\e95c"; +} + +.pi-save:before { + content: "\e95b"; +} + +.pi-question-circle:before { + content: "\e959"; +} + +.pi-question:before { + content: "\e95a"; +} + +.pi-copy:before { + content: "\e957"; +} + +.pi-file:before { + content: "\e958"; +} + +.pi-clone:before { + content: "\e955"; +} + +.pi-calendar-times:before { + content: "\e952"; +} + +.pi-calendar-minus:before { + content: "\e953"; +} + +.pi-calendar-plus:before { + content: "\e954"; +} + +.pi-ellipsis-v:before { + content: "\e950"; +} + +.pi-ellipsis-h:before { + content: "\e951"; +} + +.pi-bookmark:before { + content: "\e94e"; +} + +.pi-globe:before { + content: "\e94f"; +} + +.pi-replay:before { + content: "\e94d"; +} + +.pi-filter:before { + content: "\e94c"; +} + +.pi-print:before { + content: "\e94b"; +} + +.pi-align-right:before { + content: "\e946"; +} + +.pi-align-left:before { + content: "\e947"; +} + +.pi-align-center:before { + content: "\e948"; +} + +.pi-align-justify:before { + content: "\e949"; +} + +.pi-cog:before { + content: "\e94a"; +} + +.pi-cloud-download:before { + content: "\e943"; +} + +.pi-cloud-upload:before { + content: "\e944"; +} + +.pi-cloud:before { + content: "\e945"; +} + +.pi-pencil:before { + content: "\e942"; +} + +.pi-users:before { + content: "\e941"; +} + +.pi-clock:before { + content: "\e940"; +} + +.pi-user-minus:before { + content: "\e93e"; +} + +.pi-user-plus:before { + content: "\e93f"; +} + +.pi-trash:before { + content: "\e93d"; +} + +.pi-external-link:before { + content: "\e93c"; +} + +.pi-window-maximize:before { + content: "\e93b"; +} + +.pi-window-minimize:before { + content: "\e93a"; +} + +.pi-refresh:before { + content: "\e938"; +} + +.pi-user:before { + content: "\e939"; +} + +.pi-exclamation-triangle:before { + content: "\e922"; +} + +.pi-calendar:before { + content: "\e927"; +} + +.pi-chevron-circle-left:before { + content: "\e928"; +} + +.pi-chevron-circle-down:before { + content: "\e929"; +} + +.pi-chevron-circle-right:before { + content: "\e92a"; +} + +.pi-chevron-circle-up:before { + content: "\e92b"; +} + +.pi-angle-double-down:before { + content: "\e92c"; +} + +.pi-angle-double-left:before { + content: "\e92d"; +} + +.pi-angle-double-right:before { + content: "\e92e"; +} + +.pi-angle-double-up:before { + content: "\e92f"; +} + +.pi-angle-down:before { + content: "\e930"; +} + +.pi-angle-left:before { + content: "\e931"; +} + +.pi-angle-right:before { + content: "\e932"; +} + +.pi-angle-up:before { + content: "\e933"; +} + +.pi-upload:before { + content: "\e934"; +} + +.pi-download:before { + content: "\e956"; +} + +.pi-ban:before { + content: "\e935"; +} + +.pi-star-fill:before { + content: "\e936"; +} + +.pi-star:before { + content: "\e937"; +} + +.pi-chevron-left:before { + content: "\e900"; +} + +.pi-chevron-right:before { + content: "\e901"; +} + +.pi-chevron-down:before { + content: "\e902"; +} + +.pi-chevron-up:before { + content: "\e903"; +} + +.pi-caret-left:before { + content: "\e904"; +} + +.pi-caret-right:before { + content: "\e905"; +} + +.pi-caret-down:before { + content: "\e906"; +} + +.pi-caret-up:before { + content: "\e907"; +} + +.pi-search:before { + content: "\e908"; +} + +.pi-check:before { + content: "\e909"; +} + +.pi-check-circle:before { + content: "\e90a"; +} + +.pi-times:before { + content: "\e90b"; +} + +.pi-times-circle:before { + content: "\e90c"; +} + +.pi-plus:before { + content: "\e90d"; +} + +.pi-plus-circle:before { + content: "\e90e"; +} + +.pi-minus:before { + content: "\e90f"; +} + +.pi-minus-circle:before { + content: "\e910"; +} + +.pi-circle-on:before { + content: "\e911"; +} + +.pi-circle-off:before { + content: "\e912"; +} + +.pi-sort-down:before { + content: "\e913"; +} + +.pi-sort-up:before { + content: "\e914"; +} + +.pi-sort:before { + content: "\e915"; +} + +.pi-step-backward:before { + content: "\e916"; +} + +.pi-step-forward:before { + content: "\e917"; +} + +.pi-th-large:before { + content: "\e918"; +} + +.pi-arrow-down:before { + content: "\e919"; +} + +.pi-arrow-left:before { + content: "\e91a"; +} + +.pi-arrow-right:before { + content: "\e91b"; +} + +.pi-arrow-up:before { + content: "\e91c"; +} + +.pi-bars:before { + content: "\e91d"; +} + +.pi-arrow-circle-down:before { + content: "\e91e"; +} + +.pi-arrow-circle-left:before { + content: "\e91f"; +} + +.pi-arrow-circle-right:before { + content: "\e920"; +} + +.pi-arrow-circle-up:before { + content: "\e921"; +} + +.pi-info:before { + content: "\e923"; +} + +.pi-info-circle:before { + content: "\e924"; +} + +.pi-home:before { + content: "\e925"; +} + +.pi-spinner:before { + content: "\e926"; +} + diff --git a/components/common/Chart.vue b/components/common/Chart.vue index fd0c301..ef65aa0 100644 --- a/components/common/Chart.vue +++ b/components/common/Chart.vue @@ -1,111 +1,162 @@ - - +watch( + () => chartRef.value?.chart, + (chart) => { + if (chart) { + emit("chartReady", chart) + } + }, +) + + + diff --git a/nuxt.config.ts b/nuxt.config.ts index 661bbe7..807077f 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -1,4 +1,4 @@ -// https://nuxt.com/docs/api/configuration/nuxt-config +// https://nuxt.com/docs/api/configuration/nuxt-config import fs from "node:fs" import path from "node:path" import { PrimeVueResolver } from "@primevue/auto-import-resolver" @@ -20,11 +20,72 @@ const httpsOptions = { ), } +function sanitizeChunkName(name: string): string { + return name + .replace(/[^a-z0-9]+/gi, "-") + .replace(/^-+|-+$/g, "") + .toLowerCase() +} + +function resolvePrimevueChunk(id: string): string | null { + const formsMatch = id.match(/[/]@primevue[/]forms[/](?:dist[/]esm[/])?(.+)/) + if (formsMatch?.[1]) { + const segments = formsMatch[1].split(/[/]/).filter(Boolean) + if (segments.length > 0) { + const formsKey = + segments[0] === "components" && segments[1] + ? `component-${sanitizeChunkName(segments[1])}` + : segments[0] + return `primevue-forms-${sanitizeChunkName(formsKey)}` + } + return "primevue-forms" + } + + const themeMatch = id.match( + /[/]@primeuix[/]themes[/](?:dist[/]esm[/])?(.+)/, + ) + if (themeMatch?.[1]) { + const segments = themeMatch[1].split(/[/]/).filter(Boolean) + return `primevue-theme-${sanitizeChunkName(segments[0] ?? "core")}` + } + + const coreMatch = id.match(/[/]@primevue[/]core[/](?:dist[/]esm[/])?(.+)/) + if (coreMatch?.[1]) { + const segments = coreMatch[1].split(/[/]/).filter(Boolean) + if (segments.length > 0) { + const [first, second] = segments + if (first === "components" && second) { + return `primevue-core-${sanitizeChunkName(second)}` + } + return `primevue-core-${sanitizeChunkName(first)}` + } + return "primevue-core" + } + + const componentMatch = id.match(/[/]primevue[/](?:dist[/]esm[/])?(.+)/) + if (componentMatch?.[1]) { + const segments = componentMatch[1].split(/[/]/).filter(Boolean) + if (segments.length > 0) { + const [first, second] = segments + if (first === "components" && second) { + return `primevue-${sanitizeChunkName(second)}` + } + return `primevue-${sanitizeChunkName(first)}` + } + return "primevue-core" + } + + if (/[\\/](?:primevue|@primevue|@primeuix)[\\/]/.test(id)) { + return "primevue-core" + } + + return null +} export default defineNuxtConfig({ compatibilityDate: "2025-05-15", nitro: { preset: "cloudflare_module", // SSR用 .output/server/wrangler.json が生成される 'cloudflare' はPages用 - minify: false, + minify: true, cloudflare: { deployConfig: true, nodeCompat: true, @@ -43,7 +104,7 @@ export default defineNuxtConfig({ }, devtools: { enabled: false }, typescript: { - typeCheck: true, + typeCheck: process.env.NUXT_TYPESCRIPT_CHECK !== "false", tsConfig: { include: ["types/**/*.d.ts"], }, @@ -92,12 +153,32 @@ export default defineNuxtConfig({ }, }, css: [ - "primeicons/primeicons.css", + "@/assets/styles/primeicons.css", "@loadingio/loading.css/loading.css", "@/assets/styles/tailwind_v4.scss", "@/assets/styles/index.scss", ], modules: ["@pinia/nuxt", "@primevue/nuxt-module", "@nuxtjs/i18n"], + hooks: { + "components:extend"(components) { + for (let i = components.length - 1; i >= 0; i--) { + if ( + components[i].filePath?.includes( + "vite/modulepreload-polyfill.js", + ) + ) { + components.splice(i, 1) + } + } + }, + "imports:extend"(imports) { + for (let i = imports.length - 1; i >= 0; i--) { + if (imports[i].from === "vite/modulepreload-polyfill.js") { + imports.splice(i, 1) + } + } + }, + }, devServer: { host: "pull.log", port: 4649, @@ -109,6 +190,46 @@ export default defineNuxtConfig({ vite: { build: { sourcemap: process.env.NUXT_SOURCEMAP === "true", + rollupOptions: { + output: { + manualChunks(id) { + if (!id.includes("node_modules")) { + return undefined + } + + if ( + id.includes("chart.js") || + id.includes("chartjs-plugin") || + id.includes("vue-chartjs") + ) { + return "chart" + } + + if (/(?:^|[\\/])primeicons[\\/]/.test(id)) { + return "primeicons" + } + + const primevueChunk = resolvePrimevueChunk(id) + if (primevueChunk) { + return primevueChunk + } + + if (id.includes("luxon")) { + return "luxon" + } + + if ( + id.includes("vue-i18n") || + id.includes("@intlify") + ) { + return "i18n" + } + + return undefined + }, + }, + }, + chunkSizeWarningLimit: 1200, }, plugins: [ Components({ @@ -136,6 +257,17 @@ export default defineNuxtConfig({ primevue: { usePrimeVue: true, autoImport: true, + components: { + exclude: [ + "Dialog", + "Drawer", + "DataTable", + "Column", + "ColumnGroup", + "FileUpload", + "Editor", + ], + }, options: { theme: { preset: PullLogPreset, diff --git a/package.json b/package.json index 5730d27..ff390ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pulllog", - "version": "1.2.0", + "version": "1.2.1", "description": "Manage Your Gacha History and Analyze Statistics.", "author": "MAGIC METHODS", "license": "UNLICENSED", @@ -9,7 +9,7 @@ "type": "module", "scripts": { "clean": "rm -rf .nuxt node_modules/.vite", - "build": "NUXT_SOURCEMAP=false NUXT_TYPESCRIPT_CHECK=false nuxt build --dotenv .env.production", + "build": "cross-env NUXT_SOURCEMAP=false NUXT_TYPESCRIPT_CHECK=false nuxt build --dotenv .env.production", "dev": "nuxt dev --dotenv .env.local", "generate": "nuxt generate --dotenv .env.production", "preview": "nuxt preview --dotenv .env.production", @@ -60,6 +60,7 @@ "@types/luxon": "^3.6.2", "@types/sortablejs": "^1.15.8", "autoprefixer": "^10.4.21", + "cross-env": "^7.0.3", "husky": "^9.1.7", "lint-staged": "^16.1.6", "postcss": "^8.5.6", diff --git a/plugins/primevue-lazy.client.ts b/plugins/primevue-lazy.client.ts new file mode 100644 index 0000000..4ecf114 --- /dev/null +++ b/plugins/primevue-lazy.client.ts @@ -0,0 +1,23 @@ +import { defineAsyncComponent } from "vue" +import { defineNuxtPlugin } from "#app" + +const components = { + Dialog: () => import("primevue/dialog"), + Drawer: () => import("primevue/drawer"), + DataTable: () => import("primevue/datatable"), + Column: () => import("primevue/column"), + ColumnGroup: () => import("primevue/columngroup"), + FileUpload: () => import("primevue/fileupload"), +} as const + +export default defineNuxtPlugin((nuxtApp) => { + for (const [name, loader] of Object.entries(components)) { + nuxtApp.vueApp.component( + name, + defineAsyncComponent({ + loader: async () => (await loader()).default, + suspensible: false, + }), + ) + } +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5fa21e0..4e6d754 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -105,6 +105,9 @@ importers: autoprefixer: specifier: ^10.4.21 version: 10.4.21(postcss@8.5.6) + cross-env: + specifier: ^7.0.3 + version: 7.0.3 husky: specifier: ^9.1.7 version: 9.1.7 @@ -2356,6 +2359,11 @@ packages: resolution: {integrity: sha512-p9nwwR4qyT5W996vBZhdvBCnMhicY5ytZkR4D1Xj0wuTDEiMnjwR57Q3RXYY/s0EpX6Ay3vgIcfaR+ewGHsi+g==} engines: {node: '>=18.0'} + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -7601,6 +7609,10 @@ snapshots: croner@9.1.0: {} + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.6 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 diff --git a/public/fonts/primeicons.woff2 b/public/fonts/primeicons.woff2 new file mode 100644 index 0000000..26fb219 Binary files /dev/null and b/public/fonts/primeicons.woff2 differ