@myelophone/nuxt 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/.devcontainer/Dockerfile +7 -0
  2. package/.devcontainer/devcontainer.json +21 -0
  3. package/.editorconfig +43 -0
  4. package/.github/workflows/package.yml +73 -0
  5. package/.nuxtignore +6 -0
  6. package/.releaserc.js +132 -0
  7. package/.yarn/releases/yarn-4.18.0.cjs +1000 -0
  8. package/.yarnrc.yml +8 -0
  9. package/CHANGELOG.md +141 -0
  10. package/LICENSE +77 -0
  11. package/README.md +3004 -0
  12. package/app/app.vue +455 -0
  13. package/app/assets/css/animation.css +81 -0
  14. package/app/assets/css/backgrounds.css +57 -0
  15. package/app/assets/css/base.css +182 -0
  16. package/app/assets/css/index.css +9 -0
  17. package/app/assets/css/links.css +12 -0
  18. package/app/assets/css/multimedia.css +102 -0
  19. package/app/assets/css/preloader.css +68 -0
  20. package/app/assets/css/print.css +40 -0
  21. package/app/assets/css/tailwind.css +20 -0
  22. package/app/assets/css/theme.css +29 -0
  23. package/app/components/consent/GoogleMap.vue +59 -0
  24. package/app/components/consent/Youtube.vue +27 -0
  25. package/app/components/cookie/Banner.vue +70 -0
  26. package/app/components/cookie/ConsentWrapper.vue +71 -0
  27. package/app/components/cookie/PrivacyPolicy.vue +179 -0
  28. package/app/components/cookie/SettingsModal.vue +387 -0
  29. package/app/components/grid/Col.vue +262 -0
  30. package/app/components/grid/Container.vue +236 -0
  31. package/app/components/grid/Row.vue +248 -0
  32. package/app/components/grid/Stack.vue +233 -0
  33. package/app/components/myelophone/Copyright.vue +5 -0
  34. package/app/components/myelophone/Welcome.vue +107 -0
  35. package/app/components/page/FullscreenPreloader.vue +177 -0
  36. package/app/components/page/Preloader.vue +18 -0
  37. package/app/components/page/ReadyLocalized.vue +19 -0
  38. package/app/components/ready/.gitkeep +0 -0
  39. package/app/components/safe/Email.vue +52 -0
  40. package/app/components/safe/ImgWithLoader.vue +180 -0
  41. package/app/components/safe/NuxtImg.vue +25 -0
  42. package/app/components/safe/NuxtPicture.vue +29 -0
  43. package/app/components/section/.gitkeep +0 -0
  44. package/app/components/seo/BrandInfo.vue +76 -0
  45. package/app/components/seo/ContentNoIndex.vue +35 -0
  46. package/app/components/seo/NoIndex.vue +22 -0
  47. package/app/components/seo/OrgInfo.vue +130 -0
  48. package/app/components/seo/ProfileInfo.vue +137 -0
  49. package/app/components/ui/Accordion.vue +163 -0
  50. package/app/components/ui/Alert.vue +179 -0
  51. package/app/components/ui/Avatar.vue +88 -0
  52. package/app/components/ui/Badge.vue +150 -0
  53. package/app/components/ui/Banner.vue +133 -0
  54. package/app/components/ui/Button.vue +175 -0
  55. package/app/components/ui/Card.vue +66 -0
  56. package/app/components/ui/Checkbox.vue +134 -0
  57. package/app/components/ui/Chip.vue +136 -0
  58. package/app/components/ui/CommandPalette.vue +434 -0
  59. package/app/components/ui/Console.vue +583 -0
  60. package/app/components/ui/CursorCreative.vue +148 -0
  61. package/app/components/ui/FeatureAccordion.vue +165 -0
  62. package/app/components/ui/FileUpload.vue +705 -0
  63. package/app/components/ui/GeoDependent.vue +72 -0
  64. package/app/components/ui/Heading.vue +51 -0
  65. package/app/components/ui/Icon.vue +42 -0
  66. package/app/components/ui/Icon8.vue +39 -0
  67. package/app/components/ui/Input.vue +88 -0
  68. package/app/components/ui/LangLink.vue +34 -0
  69. package/app/components/ui/LangVisible.vue +33 -0
  70. package/app/components/ui/LanguageSelect.vue +202 -0
  71. package/app/components/ui/LightBox.vue +155 -0
  72. package/app/components/ui/LocalTime.vue +170 -0
  73. package/app/components/ui/Modal.vue +161 -0
  74. package/app/components/ui/Popup.vue +200 -0
  75. package/app/components/ui/PostContent.server.vue +23 -0
  76. package/app/components/ui/ProtectedEmail.vue +52 -0
  77. package/app/components/ui/RelativeTime.vue +141 -0
  78. package/app/components/ui/ScheduledContent.vue +150 -0
  79. package/app/components/ui/ScrollToTop.client.vue +48 -0
  80. package/app/components/ui/SegmentedControl.vue +148 -0
  81. package/app/components/ui/SiteSearch.vue +1191 -0
  82. package/app/components/ui/Skeleton.vue +91 -0
  83. package/app/components/ui/SmartContrast.vue +74 -0
  84. package/app/components/ui/SnapContainer.vue +222 -0
  85. package/app/components/ui/SnapSection.vue +294 -0
  86. package/app/components/ui/SonnerStyle.vue +7 -0
  87. package/app/components/ui/SplitSection.vue +99 -0
  88. package/app/components/ui/Steps.vue +858 -0
  89. package/app/components/ui/StickyWrapper.vue +46 -0
  90. package/app/components/ui/Table.vue +251 -0
  91. package/app/components/ui/Tabs.vue +451 -0
  92. package/app/components/ui/TextColumn.vue +36 -0
  93. package/app/components/ui/Textarea.vue +251 -0
  94. package/app/components/ui/Toggler.vue +40 -0
  95. package/app/components/ui/Tooltip.vue +524 -0
  96. package/app/components/ui/TruncateText.vue +105 -0
  97. package/app/components/ui/ViewportSpacer.vue +72 -0
  98. package/app/components/view/AnimatedCounter.vue +121 -0
  99. package/app/components/view/AnnouncementBar.vue +104 -0
  100. package/app/components/view/AvatarGroup.vue +104 -0
  101. package/app/components/view/Breadcrumbs.vue +97 -0
  102. package/app/components/view/ContentWithToc.vue +152 -0
  103. package/app/components/view/Copyright.vue +68 -0
  104. package/app/components/view/CountdownTimer.vue +184 -0
  105. package/app/components/view/CreativeCTA.vue +143 -0
  106. package/app/components/view/CurrencySelect.vue +254 -0
  107. package/app/components/view/FeatureBoxGrid.vue +142 -0
  108. package/app/components/view/HorizontalMenu.vue +97 -0
  109. package/app/components/view/ImageCompare.vue +141 -0
  110. package/app/components/view/ImgSlider.vue +333 -0
  111. package/app/components/view/InfiniteMarquee.vue +147 -0
  112. package/app/components/view/InfoBar.vue +86 -0
  113. package/app/components/view/LogoGrid.vue +106 -0
  114. package/app/components/view/LogoSlider.vue +83 -0
  115. package/app/components/view/NotFound.vue +81 -0
  116. package/app/components/view/PartialBackground.vue +313 -0
  117. package/app/components/view/QuoteBig.vue +111 -0
  118. package/app/components/view/ResponsiveMenu.vue +219 -0
  119. package/app/components/view/ReviewsSlider.vue +230 -0
  120. package/app/components/view/SocialBar.vue +78 -0
  121. package/app/components/view/StickyHeadingContent.vue +158 -0
  122. package/app/components/view/TallyForm.vue +295 -0
  123. package/app/components/view/WarningOutdated.vue +113 -0
  124. package/app/composables/useApi.ts +88 -0
  125. package/app/composables/useAppSeo.ts +78 -0
  126. package/app/composables/useBreadcrumbs.ts +106 -0
  127. package/app/composables/useChangeUrl.ts +73 -0
  128. package/app/composables/useCommand.ts +28 -0
  129. package/app/composables/useCookieControl.ts +111 -0
  130. package/app/composables/useCookieModal.ts +9 -0
  131. package/app/composables/useDevice.ts +109 -0
  132. package/app/composables/useGeoFetch.ts +139 -0
  133. package/app/composables/useLoadScript.ts +36 -0
  134. package/app/composables/useModalState.ts +37 -0
  135. package/app/composables/useMultiLang.ts +278 -0
  136. package/app/composables/useNetwork.ts +49 -0
  137. package/app/composables/useNuxtVersion.ts +5 -0
  138. package/app/composables/usePiniaStore.ts +5 -0
  139. package/app/composables/usePopupControl.ts +57 -0
  140. package/app/composables/useQuery.ts +307 -0
  141. package/app/composables/useReadyPage.ts +182 -0
  142. package/app/composables/useSafeList.ts +90 -0
  143. package/app/composables/useScriptLoader.ts +221 -0
  144. package/app/composables/useSiteSearch.ts +32 -0
  145. package/app/composables/useSnapScroll.ts +24 -0
  146. package/app/composables/useStatic.ts +5 -0
  147. package/app/composables/useStorage.ts +252 -0
  148. package/app/composables/useStoreBroadcast.ts +146 -0
  149. package/app/composables/useThemeSync.ts +81 -0
  150. package/app/constants/layout.ts +109 -0
  151. package/app/constants/predefinedCookieScripts.ts +1222 -0
  152. package/app/constants/ui-events.ts +1 -0
  153. package/app/error.vue +169 -0
  154. package/app/layouts/default-blog.vue +5 -0
  155. package/app/layouts/default.vue +3 -0
  156. package/app/locales/en/commands.json +5 -0
  157. package/app/locales/en/cookies.json +182 -0
  158. package/app/locales/en/error.json +4 -0
  159. package/app/locales/en/interface.json +33 -0
  160. package/app/locales/en/myelophone.json +8 -0
  161. package/app/locales/en/outdated.json +5 -0
  162. package/app/locales/en/times.json +18 -0
  163. package/app/locales/pl/commands.json +5 -0
  164. package/app/locales/pl/cookies.json +182 -0
  165. package/app/locales/pl/error.json +4 -0
  166. package/app/locales/pl/interface.json +33 -0
  167. package/app/locales/pl/myelophone.json +8 -0
  168. package/app/locales/pl/outdated.json +5 -0
  169. package/app/locales/pl/times.json +18 -0
  170. package/app/locales/ru/commands.json +5 -0
  171. package/app/locales/ru/cookies.json +182 -0
  172. package/app/locales/ru/error.json +4 -0
  173. package/app/locales/ru/interface.json +33 -0
  174. package/app/locales/ru/myelophone.json +8 -0
  175. package/app/locales/ru/outdated.json +5 -0
  176. package/app/locales/ru/times.json +18 -0
  177. package/app/middleware/blog-layout.ts +28 -0
  178. package/app/middleware/i18n.global.ts +17 -0
  179. package/app/middleware/not-found-status.ts +11 -0
  180. package/app/modules/default-blog/index.ts +39 -0
  181. package/app/modules/default-blog/posts.ts +80 -0
  182. package/app/modules/default-sitemap/index.ts +116 -0
  183. package/app/modules/default-sitemap/runtime/sitemap.get.ts +42 -0
  184. package/app/modules/fullscreen-preloader/module.ts +43 -0
  185. package/app/modules/htaccess/.htaccess +38 -0
  186. package/app/modules/htaccess/index.ts +23 -0
  187. package/app/modules/i18n-shaker.mjs +221 -0
  188. package/app/modules/multi18n/module.ts +71 -0
  189. package/app/modules/myelophone-config/module.ts +241 -0
  190. package/app/pages/[...all].vue +9 -0
  191. package/app/pages/index.vue +3 -0
  192. package/app/pages/post/[...slug].vue +30 -0
  193. package/app/plugins/bfcache-refresh.client.ts +9 -0
  194. package/app/plugins/canonical.ts +30 -0
  195. package/app/plugins/csp-nonce.server.ts +41 -0
  196. package/app/plugins/multi18n.client.ts +21 -0
  197. package/app/plugins/multi18n.server.ts +15 -0
  198. package/app/plugins/nuxt-version.client.ts +4 -0
  199. package/app/plugins/restore.client.ts +21 -0
  200. package/app/plugins/reveal.ts +89 -0
  201. package/app/plugins/url-helper.client.ts +66 -0
  202. package/app/server/api/exchange-rates.get.ts +216 -0
  203. package/app/server/api/healthz.ts +1 -0
  204. package/app/server/api/logout.post.ts +6 -0
  205. package/app/server/middleware/normalize-url.ts +14 -0
  206. package/app/server/middleware/security-headers.ts +147 -0
  207. package/app/server/middleware/url-helper.ts +43 -0
  208. package/app/server/plugins/clean-html-spaces.ts +15 -0
  209. package/app/server/plugins/clean-styles.ts +94 -0
  210. package/app/server/plugins/compression.ts +122 -0
  211. package/app/server/plugins/css-preload.ts +26 -0
  212. package/app/server/plugins/early-hints.ts +31 -0
  213. package/app/server/plugins/force-noindex.ts +43 -0
  214. package/app/server/plugins/html-one-line.ts +17 -0
  215. package/app/server/plugins/inline-style.ts +7 -0
  216. package/app/server/routes/healthz.get.ts +1 -0
  217. package/app/server/tsconfig.json +3 -0
  218. package/app/stores/cart.ts +945 -0
  219. package/app/stores/commands.ts +43 -0
  220. package/app/stores/device.ts +156 -0
  221. package/app/stores/querySync.ts +5 -0
  222. package/app/stores/settings.ts +145 -0
  223. package/app/stores/user.ts +607 -0
  224. package/app/types/cookie.ts +89 -0
  225. package/app/types/myelophone.d.ts +87 -0
  226. package/app/types/site-search.ts +110 -0
  227. package/app/utils/asyncRefresh.ts +4 -0
  228. package/app/utils/blog.server.ts +142 -0
  229. package/app/utils/jsonLd.ts +56 -0
  230. package/app/utils/myelophoneConfig.ts +4 -0
  231. package/app/utils/sortBy.ts +18 -0
  232. package/app/utils/transliterate.ts +75 -0
  233. package/app/utils/ytVideo.ts +37 -0
  234. package/app/workers/site-search.worker.ts +661 -0
  235. package/biome.json +94 -0
  236. package/commitlint.config.js +3 -0
  237. package/nuxt.config.ts +539 -0
  238. package/package.json +101 -0
  239. package/playground/content/.gitkeep +0 -0
  240. package/playground/locales/.gitkeep +0 -0
  241. package/playground/myelophone.dev.ts +45 -0
  242. package/playground/nuxt.config.ts +105 -0
  243. package/playground/package.json +5 -0
  244. package/playground/pages/.gitkeep +0 -0
  245. package/playground/tsconfig.json +3 -0
  246. package/playwright.config.ts +23 -0
  247. package/public/browsers/chrome.svg +77 -0
  248. package/public/browsers/edge.svg +98 -0
  249. package/public/browsers/firefox.svg +300 -0
  250. package/public/favicon.ico +0 -0
  251. package/public/myelophone_eng.png +0 -0
  252. package/public/myelophone_eng_white.png +0 -0
  253. package/spa-loading-template.html +72 -0
  254. package/tests/home.spec.ts +9 -0
  255. package/tests/utils.ts +23 -0
  256. package/tsconfig.json +16 -0
  257. package/vite/plugins/clean-css.ts +190 -0
  258. package/vite/plugins/postcss-add-viewportunits.ts +33 -0
  259. package/vite/plugins/postcss-viewport-fallback.ts +49 -0
package/biome.json ADDED
@@ -0,0 +1,94 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.5.11/schema.json",
3
+ "assist": {
4
+ "actions": {
5
+ "source": {
6
+ "organizeImports": "off"
7
+ }
8
+ }
9
+ },
10
+ "formatter": {
11
+ "enabled": true,
12
+ "indentWidth": 4,
13
+ "indentStyle": "tab",
14
+ "lineWidth": 120
15
+ },
16
+ "linter": {
17
+ "enabled": true,
18
+ "rules": {
19
+ "recommended": true,
20
+ "complexity": {
21
+ "noForEach": "off"
22
+ },
23
+ "suspicious": {
24
+ "noArrayIndexKey": "off",
25
+ "noExplicitAny": "warn",
26
+ "noAssignInExpressions": "off"
27
+ },
28
+ "a11y": {
29
+ "useKeyWithClickEvents": "off",
30
+ "noSvgWithoutTitle": "off",
31
+ "useButtonType": "off"
32
+ },
33
+ "style": {
34
+ "noNonNullAssertion": "off",
35
+ "noParameterAssign": "error",
36
+ "useAsConstAssertion": "error",
37
+ "useDefaultParameterLast": "error",
38
+ "useEnumInitializers": "error",
39
+ "useSelfClosingElements": "error",
40
+ "useSingleVarDeclarator": "error",
41
+ "noUnusedTemplateLiteral": "error",
42
+ "useNumberNamespace": "error",
43
+ "noInferrableTypes": "error",
44
+ "noUselessElse": "error"
45
+ },
46
+ "correctness": {
47
+ "useExhaustiveDependencies": "off"
48
+ }
49
+ }
50
+ },
51
+ "vcs": {
52
+ "enabled": true,
53
+ "defaultBranch": "main",
54
+ "clientKind": "git",
55
+ "useIgnoreFile": false
56
+ },
57
+ "files": {
58
+ "includes": [
59
+ "**",
60
+ "!**/dist",
61
+ "!**/*.cjs",
62
+ "!**/*.mjs",
63
+ "!**/*.d.ts",
64
+ "!**/node_modules",
65
+ "!**/.yarn"
66
+ ]
67
+ },
68
+ "javascript": {
69
+ "formatter": {
70
+ "enabled": true,
71
+ "quoteStyle": "single",
72
+ "jsxQuoteStyle": "double",
73
+ "semicolons": "asNeeded",
74
+ "trailingCommas": "none"
75
+ }
76
+ },
77
+ "json": {
78
+ "formatter": {
79
+ "trailingCommas": "none"
80
+ }
81
+ },
82
+ "overrides": [
83
+ {
84
+ "includes": ["**/*.vue"],
85
+ "linter": {
86
+ "rules": {
87
+ "correctness": {
88
+ "noUnusedVariables": "off"
89
+ }
90
+ }
91
+ }
92
+ }
93
+ ]
94
+ }
@@ -0,0 +1,3 @@
1
+ export default {
2
+ extends: ['@commitlint/config-conventional'],
3
+ };
package/nuxt.config.ts ADDED
@@ -0,0 +1,539 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import multi18n from './app/modules/multi18n/module';
5
+ import myelophoneConfig from './app/modules/myelophone-config/module';
6
+ import i18nTreeShaker from './app/modules/i18n-shaker.mjs';
7
+ import nuxtHtaccess from './app/modules/htaccess';
8
+ import fullscreenPreloader from './app/modules/fullscreen-preloader/module';
9
+ import defaultBlog from './app/modules/default-blog';
10
+ import defaultSitemap from './app/modules/default-sitemap';
11
+
12
+ import { cleanEmptyCssPlugin } from './vite/plugins/clean-css';
13
+ import postcssViewportFallback from './vite/plugins/postcss-viewport-fallback';
14
+ import noImportant from 'postcss-no-important';
15
+ import postcssAddViewportUnits from './vite/plugins/postcss-add-viewportunits';
16
+
17
+ import tailwindcss from '@tailwindcss/vite';
18
+
19
+ import { createResolver, useNuxt, extendViteConfig } from '@nuxt/kit';
20
+
21
+ const pkg = JSON.parse(
22
+ readFileSync(new URL('./package.json', import.meta.url), 'utf8'),
23
+ );
24
+
25
+ const version = pkg.version;
26
+
27
+ const dateActuality = '2026-08-31';
28
+ const banner = `/* © 2025 Aliaksandr Ivanou (https://aleksivanov.me/). All rights reserved. @MyelophOne/Nuxt v${version}. This app bundle licenses: /_nuxt/licenses.md */\n`;
29
+ const defaultSeo = {
30
+ title: 'Our Nuxt WebSite | by MyelophOne/Nuxt',
31
+ description:
32
+ 'Welcome to our new amazing website where you can explore exciting content and features! Empowered by MyelophOne',
33
+ };
34
+
35
+ const isSSG = process.env.NUXT_STATIC === 'true';
36
+ const isPlayground = process.env.NUXT_PLAYGROUND === 'true';
37
+
38
+ const moreModules: string[] = [];
39
+ const { resolve } = createResolver(import.meta.url);
40
+ const serverScanDirs = [
41
+ resolve('./app/server'),
42
+ resolve('./server'),
43
+ path.resolve(process.cwd(), 'app/server'),
44
+ path.resolve(process.cwd(), 'server'),
45
+ ].filter((dir, index, dirs) => dirs.indexOf(dir) === index);
46
+ const i18nScanDirs = [
47
+ resolve('./app'),
48
+ path.resolve(process.cwd(), 'app'),
49
+ ...(isPlayground ? [path.resolve(process.cwd(), 'playground')] : []),
50
+ ];
51
+
52
+ export default defineNuxtConfig({
53
+ compatibilityDate: dateActuality,
54
+ alias: {
55
+ '#myelophone-nuxt-locales': resolve('./app/locales'),
56
+ '#myelophone': resolve('./'),
57
+ },
58
+ modules: [
59
+ '@pinia/nuxt',
60
+ '@pinia/colada-nuxt',
61
+ '@nuxtjs/robots',
62
+ 'nuxt-link-checker',
63
+ 'nuxt-seo-utils',
64
+ 'nuxt-og-image',
65
+ '@nuxtjs/fontaine',
66
+ '@nuxt/scripts',
67
+ '@nuxt/image',
68
+ '@nuxt/fonts',
69
+ 'nuxt-security',
70
+ 'nuxt-api-party',
71
+ 'vue-sonner/nuxt',
72
+ 'nuxt-vitalizer',
73
+ ...moreModules,
74
+ myelophoneConfig,
75
+ multi18n,
76
+ nuxtHtaccess,
77
+ fullscreenPreloader,
78
+ defaultBlog,
79
+ defaultSitemap,
80
+ ],
81
+ features: {
82
+ inlineStyles: false,
83
+ },
84
+ future: {
85
+ compatibilityVersion: 5,
86
+ },
87
+ experimental: {
88
+ writeEarlyHints: true,
89
+ entryImportMap: false,
90
+ restoreState: true,
91
+ viewTransition: true,
92
+ componentIslands: true,
93
+ clientFallback: true,
94
+ typedPages: true,
95
+ payloadExtraction: isSSG ? false : 'client',
96
+ nitroAutoImports: true,
97
+ prefetchPreloadTags: true,
98
+ watcher: 'builder',
99
+ viteEnvironmentApi: false,
100
+ defaults: {
101
+ nuxtLink: {
102
+ prefetchOn: {
103
+ interaction: true,
104
+ visibility: false,
105
+ },
106
+ },
107
+ },
108
+ },
109
+ devtools: { enabled: process.env.NODE_ENV === 'development' },
110
+ app: {
111
+ head: {
112
+ meta: [
113
+ {
114
+ name: 'viewport',
115
+ content:
116
+ 'width=device-width, initial-scale=1, viewport-fit=cover',
117
+ },
118
+ ],
119
+ htmlAttrs: {
120
+ class: 'nojs',
121
+ dir: 'ltr',
122
+ },
123
+ script: [
124
+ {
125
+ innerHTML: `!function(){try{let e={light:"light",dark:"dark"},t=window?.localStorage?.getItem("theme")||"",a=window.matchMedia("(prefers-color-scheme: dark)"),c=Object.values(e).includes(t)?t:a.matches?e.dark:e.light;document.documentElement.setAttribute("data-theme",c)}catch(l){}}();document.documentElement.classList.replace('nojs', 'js')`,
126
+ tagPosition: 'head',
127
+ },
128
+ ],
129
+ },
130
+ },
131
+ appConfig: {
132
+ defaultSeo,
133
+ },
134
+ ogImage: {
135
+ enabled: process.env.NODE_ENV !== 'test',
136
+ zeroRuntime: true,
137
+ },
138
+ nitro: {
139
+ scanDirs: serverScanDirs,
140
+ preset: isSSG ? 'static' : process.env.NITRO_PRESET || 'node-cluster',
141
+ compressPublicAssets: true,
142
+ externals: {
143
+ inline: ['h3', '@vue/shared'],
144
+ },
145
+ experimental: {
146
+ tasks: true,
147
+ database: true,
148
+ },
149
+ storage: {},
150
+ devStorage: {},
151
+ database: {},
152
+ prerender: isSSG
153
+ ? {
154
+ failOnError: false,
155
+ crawlLinks: true,
156
+ ignore: [
157
+ (path: string) => path.match(/\.(js|css|map|json)$/),
158
+ ],
159
+ }
160
+ : undefined,
161
+ },
162
+ vite: {
163
+ clearScreen: false,
164
+ build: {
165
+ cssMinify: 'esbuild',
166
+ sourcemap: process.env.NODE_ENV === 'development',
167
+ assetsInlineLimit: 4096,
168
+ license: {
169
+ fileName: '_nuxt/licenses.md',
170
+ },
171
+ rolldownOptions: {
172
+ treeshake: {
173
+ manualPureFunctions: [
174
+ 'console.log',
175
+ 'console.error',
176
+ 'console.debug',
177
+ 'console.trace',
178
+ ],
179
+ },
180
+ },
181
+ },
182
+ css: {
183
+ devSourcemap: true,
184
+ },
185
+ plugins: [
186
+ tailwindcss(),
187
+ {
188
+ name: 'suppress-plugin-timings-warning',
189
+ configResolved(config) {
190
+ const originalLogger = config.logger.warn;
191
+
192
+ config.logger.warn = (msg, options) => {
193
+ if (
194
+ typeof msg === 'string' &&
195
+ msg.includes('[PLUGIN_TIMINGS]')
196
+ ) {
197
+ return;
198
+ }
199
+
200
+ originalLogger(msg, options);
201
+ };
202
+ },
203
+ },
204
+ {
205
+ apply: 'build',
206
+ name: 'vite-plugin-ignore-sourcemap-warnings',
207
+ configResolved(config) {
208
+ const options = config.build.rolldownOptions;
209
+ if (!options) return;
210
+
211
+ const originalOnLog = options.onLog;
212
+
213
+ options.onLog = (level, log, defaultHandler) => {
214
+ if (log.code === 'SOURCEMAP_BROKEN') {
215
+ return;
216
+ }
217
+
218
+ if (originalOnLog) {
219
+ originalOnLog(level, log, defaultHandler);
220
+ } else {
221
+ defaultHandler(level, log);
222
+ }
223
+ };
224
+ },
225
+ },
226
+ {
227
+ name: 'nuxt-add-banner',
228
+ generateBundle(_, bundle) {
229
+ for (const file of Object.values(bundle)) {
230
+ if (file.type === 'chunk') {
231
+ if (
232
+ file.fileName.endsWith('.js') &&
233
+ 'code' in file
234
+ ) {
235
+ file.code = banner + file.code;
236
+ }
237
+ } else if (file.type === 'asset') {
238
+ if (
239
+ file.fileName.endsWith('.css') &&
240
+ 'source' in file
241
+ ) {
242
+ file.source = banner + file.source;
243
+ }
244
+ }
245
+ }
246
+ },
247
+ },
248
+ (i18nTreeShaker as any)({
249
+ localesDir: 'locales',
250
+ safelistPath: './i18n-safelist.json',
251
+ scanDirs: i18nScanDirs,
252
+ }),
253
+ cleanEmptyCssPlugin({
254
+ purgeTailwindUtilities: true,
255
+ postcssPlugins: [
256
+ postcssViewportFallback(),
257
+ noImportant(),
258
+ postcssAddViewportUnits(),
259
+ ],
260
+ }),
261
+ ],
262
+ server: {
263
+ fs: {
264
+ strict: false,
265
+ },
266
+ },
267
+ optimizeDeps: {
268
+ exclude: ['vue'],
269
+ include: ['@vue/devtools-core', '@vue/devtools-kit'],
270
+ },
271
+ },
272
+ security: {
273
+ strict: true,
274
+ removeLoggers: false,
275
+ sri: false,
276
+ hidePoweredBy: true,
277
+ headers: {
278
+ contentSecurityPolicy: {
279
+ 'default-src': ["'self'"],
280
+ 'base-uri': ["'none'"],
281
+ 'connect-src': ["'self'", 'https:'],
282
+ 'font-src': ["'self'", 'https:', 'data:'],
283
+ 'form-action': ["'self'"],
284
+ 'frame-ancestors': ["'self'"],
285
+ 'img-src': ["'self'", 'data:', 'blob:', 'https:'],
286
+ 'media-src': ["'self'", 'https:', 'blob:'],
287
+ 'object-src': ["'none'"],
288
+ 'worker-src': ["'self'", 'blob:'],
289
+ 'style-src': ["'self'", 'https:', "'unsafe-inline'"],
290
+ 'script-src': ["'nonce-{{nonce}}'", "'strict-dynamic'"],
291
+ 'script-src-attr': ["'none'"],
292
+ 'frame-src': ["'self'", 'https:'],
293
+ 'upgrade-insecure-requests': true,
294
+ },
295
+ originAgentCluster: '?1',
296
+ referrerPolicy: 'strict-origin-when-cross-origin',
297
+ xXSSProtection: '1',
298
+ strictTransportSecurity: {
299
+ maxAge: 31536000,
300
+ includeSubdomains: true,
301
+ preload: true,
302
+ },
303
+ crossOriginResourcePolicy: 'same-origin',
304
+ crossOriginOpenerPolicy: 'same-origin',
305
+ crossOriginEmbedderPolicy: 'unsafe-none',
306
+ xContentTypeOptions: 'nosniff',
307
+ xDNSPrefetchControl: 'on',
308
+ xDownloadOptions: 'noopen',
309
+ xFrameOptions: 'SAMEORIGIN',
310
+ xPermittedCrossDomainPolicies: 'none',
311
+ permissionsPolicy: {
312
+ 'picture-in-picture': ['self', '*'],
313
+ fullscreen: ['self', '*'],
314
+ autoplay: ['self', '*'],
315
+ geolocation: ['self'],
316
+ camera: ['self'],
317
+ microphone: ['self'],
318
+ payment: ['self'],
319
+ },
320
+ },
321
+ requestSizeLimiter: {
322
+ maxRequestSizeInBytes: 2000000,
323
+ maxUploadFileRequestInBytes: 10485760,
324
+ throwError: true,
325
+ },
326
+ rateLimiter: {
327
+ tokensPerInterval: 150,
328
+ interval: 300000,
329
+ headers: true,
330
+ driver: {
331
+ name: 'lruCache',
332
+ },
333
+ throwError: true,
334
+ },
335
+ corsHandler: {
336
+ origin: '*',
337
+ methods: [
338
+ 'GET',
339
+ 'HEAD',
340
+ 'PUT',
341
+ 'PATCH',
342
+ 'POST',
343
+ 'DELETE',
344
+ 'OPTIONS',
345
+ ],
346
+ preflight: {
347
+ statusCode: 204,
348
+ },
349
+ },
350
+ allowedMethodsRestricter: {
351
+ methods: [
352
+ 'GET',
353
+ 'POST',
354
+ 'PUT',
355
+ 'DELETE',
356
+ 'PATCH',
357
+ 'HEAD',
358
+ 'OPTIONS',
359
+ ],
360
+ throwError: true,
361
+ },
362
+ basicAuth: false,
363
+ enabled: true,
364
+ csrf: false,
365
+ nonce: true,
366
+ ssg: {
367
+ meta: false,
368
+ hashScripts: false,
369
+ hashStyles: false,
370
+ nitroHeaders: false,
371
+ exportToPresets: true,
372
+ },
373
+ },
374
+ image: {
375
+ domains: ['img.youtube.com', 'i.vimeocdn.com'],
376
+ alias: {
377
+ youtube: 'https://img.youtube.com',
378
+ vimeo: 'https://i.vimeocdn.com',
379
+ },
380
+ provider: isSSG ? 'none' : 'ipx',
381
+ ipx: {
382
+ maxAge: 31536000,
383
+ },
384
+ },
385
+ robots: {
386
+ blockNonSeoBots: true,
387
+ },
388
+ apiParty: {
389
+ endpoints: {
390
+ jsonPlaceholder: {
391
+ url:
392
+ process.env.JSON_PLACEHOLDER_API_BASE_URL! ||
393
+ 'https://jsonplaceholder.typicode.com',
394
+ },
395
+ },
396
+ },
397
+ imports: {
398
+ dirs: ['stores', 'constants'],
399
+ },
400
+ serverDir: 'app/server',
401
+ routeRules: {
402
+ '/_nuxt/**': {
403
+ headers: {
404
+ 'cache-control': 'public, max-age=31536000, immutable',
405
+ },
406
+ },
407
+ '/_ipx/**': { swr: false },
408
+ },
409
+ seo: {
410
+ automaticDefaults: false,
411
+ },
412
+ multi18n: {
413
+ locales: ['en'],
414
+ defaultLocale: 'en',
415
+ },
416
+ sourcemap: {
417
+ server: true,
418
+ client: process.env.NODE_ENV === 'development',
419
+ },
420
+ vueSonner: {
421
+ css: false,
422
+ },
423
+ hooks: {
424
+ 'nitro:config'(nitroConfig) {
425
+ if (process.platform !== 'win32') {
426
+ return;
427
+ }
428
+
429
+ nitroConfig.rollupConfig ||= {};
430
+ const resolver = {
431
+ name: 'resolve-nuxt-cache-driver-file-url',
432
+ resolveId(source: string) {
433
+ if (
434
+ source.startsWith('file:') &&
435
+ source.endsWith('/runtime/utils/cache-driver.mjs')
436
+ ) {
437
+ return fileURLToPath(source);
438
+ }
439
+ },
440
+ };
441
+ const plugins = nitroConfig.rollupConfig.plugins;
442
+
443
+ nitroConfig.rollupConfig.plugins = plugins
444
+ ? Array.isArray(plugins)
445
+ ? [...plugins, resolver]
446
+ : [plugins, resolver]
447
+ : [resolver];
448
+ },
449
+ 'build:manifest': (manifest) => {
450
+ for (const key in manifest) {
451
+ const item = manifest[key];
452
+ if (item) {
453
+ if (key.includes('entry')) {
454
+ item.preload = true;
455
+ } else {
456
+ item.preload = false;
457
+ }
458
+ }
459
+ }
460
+ },
461
+ 'modules:done'() {
462
+ const nuxt = useNuxt();
463
+ const bundleTranslations =
464
+ nuxt.options.myelophone?.bundleTranslations ?? true;
465
+
466
+ extendViteConfig((config) => {
467
+ const output = config.build?.rolldownOptions?.output;
468
+
469
+ if (
470
+ output &&
471
+ typeof output === 'object' &&
472
+ !Array.isArray(output)
473
+ ) {
474
+ output.codeSplitting = {
475
+ groups: [
476
+ {
477
+ name(id: string): string | null {
478
+ if (id.includes('vue-sonner')) {
479
+ return 'sonner';
480
+ }
481
+
482
+ if (bundleTranslations) return null;
483
+
484
+ const cleanId =
485
+ id.split('?')[0]?.replace(/\\/g, '/') ||
486
+ '';
487
+
488
+ if (
489
+ cleanId.includes('/locales/') &&
490
+ cleanId.endsWith('.json')
491
+ ) {
492
+ const shouldSkip =
493
+ cleanId.includes('/playground/') ||
494
+ cleanId.includes('/admin/') ||
495
+ cleanId.includes('/split/') ||
496
+ cleanId.endsWith('admin.json') ||
497
+ cleanId.endsWith('split.json');
498
+
499
+ if (shouldSkip) return null;
500
+
501
+ const parts =
502
+ cleanId.split('/locales/');
503
+ const afterLocales = parts[1];
504
+
505
+ if (afterLocales) {
506
+ const lang =
507
+ afterLocales.split('/')[0];
508
+ if (lang) {
509
+ return `i18n-${lang}`;
510
+ }
511
+ }
512
+ }
513
+
514
+ return null;
515
+ },
516
+ },
517
+ ],
518
+ };
519
+
520
+ output.assetFileNames = (assetInfo) => {
521
+ const isCss = assetInfo.names?.some((name) =>
522
+ name.endsWith('.css'),
523
+ );
524
+
525
+ if (isCss) {
526
+ return '_nuxt/[hash][extname]';
527
+ }
528
+ return '_nuxt/[name].[hash][extname]';
529
+ };
530
+ }
531
+ });
532
+ },
533
+ },
534
+ runtimeConfig: {
535
+ public: {
536
+ version,
537
+ },
538
+ },
539
+ });