@dargmuesli/nuxt-vio 17.0.4 → 18.0.0
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.
- package/.config/lint.js +1 -2
- package/{components → app/components}/vio/_/VioApp.vue +7 -18
- package/{components → app/components}/vio/_/VioError.vue +1 -3
- package/{components → app/components}/vio/_/VioLink.vue +0 -2
- package/{components → app/components}/vio/form/VioForm.vue +0 -2
- package/{components → app/components}/vio/loader/Loader.vue +0 -2
- package/{components → app/components}/vio/page/VioPageLegalNotice.vue +0 -3
- package/{components → app/components}/vio/page/VioPagePrivacyPolicy.vue +0 -3
- package/app/composables/head.ts +115 -0
- package/app/composables/networking.ts +30 -0
- package/{error.vue → app/error.vue} +2 -1
- package/app/pages/legal-notice.vue +20 -0
- package/{pages → app/pages}/privacy-policy.vue +33 -16
- package/i18n/i18n.config.ts +0 -2
- package/i18n/locales/de.json +1 -0
- package/i18n/locales/en.json +1 -0
- package/nuxt.config.ts +16 -9
- package/package.json +18 -30
- package/server/middleware/headers.ts +0 -2
- package/server/plugins/security.ts +1 -2
- package/{composables/useGetServiceHref.ts → server/utils/networking.ts} +10 -1
- package/server/utils/testing.ts +0 -1
- package/server/utils/timezone.ts +0 -2
- package/{utils → shared/utils}/auth.ts +1 -2
- package/{utils → shared/utils}/constants.ts +6 -6
- package/{utils → shared/utils}/networking.ts +6 -7
- package/composables/useAppLayout.ts +0 -28
- package/composables/useFavicons.ts +0 -21
- package/composables/useHeadDefault.ts +0 -25
- package/composables/useHost.ts +0 -9
- package/composables/usePolyfills.ts +0 -28
- package/pages/legal-notice.vue +0 -3
- /package/{app.config.ts → app/app.config.ts} +0 -0
- /package/{assets → app/assets}/css/forms.css +0 -0
- /package/{assets → app/assets}/css/vio.css +0 -0
- /package/{components → app/components}/vio/button/VioButton.vue +0 -0
- /package/{components → app/components}/vio/button/VioButtonColored.vue +0 -0
- /package/{components → app/components}/vio/button/VioButtonHome.vue +0 -0
- /package/{components → app/components}/vio/button/VioButtonIcon.vue +0 -0
- /package/{components → app/components}/vio/button/VioButtonList.vue +0 -0
- /package/{components → app/components}/vio/button/VioButtonShare.vue +0 -0
- /package/{components → app/components}/vio/card/VioCard.vue +0 -0
- /package/{components → app/components}/vio/card/state/VioCardState.vue +0 -0
- /package/{components → app/components}/vio/card/state/VioCardStateAlert.vue +0 -0
- /package/{components → app/components}/vio/card/state/VioCardStateInfo.vue +0 -0
- /package/{components → app/components}/vio/form/VioFormCheckbox.vue +0 -0
- /package/{components → app/components}/vio/form/VioFormContact.vue +0 -0
- /package/{components → app/components}/vio/form/input/VioFormInput.vue +0 -0
- /package/{components → app/components}/vio/form/input/VioFormInputEmailAddress.vue +0 -0
- /package/{components → app/components}/vio/form/input/VioFormInputIconWrapper.vue +0 -0
- /package/{components → app/components}/vio/form/input/VioFormInputUrl.vue +0 -0
- /package/{components → app/components}/vio/form/input/state/VioFormInputState.vue +0 -0
- /package/{components → app/components}/vio/form/input/state/VioFormInputStateError.vue +0 -0
- /package/{components → app/components}/vio/form/input/state/VioFormInputStateInfo.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconArrowLeft.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconArrowRight.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconCalendar.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconChartBar.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconChatOutline.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconChatSolid.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconCheckCircle.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconContainer.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconDownload.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconExclamationCircle.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconHeart.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconHome.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconHourglass.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconLightbulb.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconMixcloud.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconMusic.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconPlay.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconShare.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconSignIn.vue +0 -0
- /package/{components → app/components}/vio/icon/VioIconTv.vue +0 -0
- /package/{components → app/components}/vio/layout/VioLayout.vue +0 -0
- /package/{components → app/components}/vio/layout/VioLayoutBreadcrumbs.vue +0 -0
- /package/{components → app/components}/vio/layout/VioLayoutFooter.vue +0 -0
- /package/{components → app/components}/vio/layout/VioLayoutFooterCategory.vue +0 -0
- /package/{components → app/components}/vio/layout/VioLayoutHr.vue +0 -0
- /package/{components → app/components}/vio/layout/VioLayoutProse.vue +0 -0
- /package/{components → app/components}/vio/layout/VioLayoutSpanList.vue +0 -0
- /package/{components → app/components}/vio/layout/VioLayoutTbody.vue +0 -0
- /package/{components → app/components}/vio/layout/VioLayoutThead.vue +0 -0
- /package/{components → app/components}/vio/loader/LoaderImage.vue +0 -0
- /package/{components → app/components}/vio/loader/indicator/LoaderIndicatorText.vue +0 -0
- /package/{components → app/components}/vio/loader/indicator/VioLoaderIndicator.vue +0 -0
- /package/{components → app/components}/vio/loader/indicator/VioLoaderIndicatorPing.vue +0 -0
- /package/{components → app/components}/vio/loader/indicator/VioLoaderIndicatorSpinner.vue +0 -0
- /package/{composables/useFireError.ts → app/composables/alert.ts} +0 -0
- /package/{composables → app/composables}/dateTime.ts +0 -0
- /package/{composables/useVioGtag.ts → app/composables/gtag.ts} +0 -0
- /package/{composables/useLoadingDoneIndicator.ts → app/composables/loading.ts} +0 -0
- /package/{composables/useStrapiFetch.ts → app/composables/strapi.ts} +0 -0
- /package/{composables → app/composables}/testing.ts +0 -0
- /package/{layouts → app/layouts}/default.vue +0 -0
- /package/{plugins → app/plugins}/dayjs.ts +0 -0
- /package/{plugins → app/plugins}/i18n.ts +0 -0
- /package/{store → app/stores}/auth.ts +0 -0
- /package/{types → shared/types}/api.d.ts +0 -0
- /package/{types → shared/types}/fetch.d.ts +0 -0
- /package/{types → shared/types}/i18n.d.ts +0 -0
- /package/{types → shared/types}/modules/gql.d.ts +0 -0
- /package/{types → shared/types}/modules/graphql.d.ts +0 -0
- /package/{utils → shared/utils}/form.ts +0 -0
- /package/{utils → shared/utils}/modal.ts +0 -0
- /package/{utils → shared/utils}/nuxt.ts +0 -0
- /package/{utils → shared/utils}/text.ts +0 -0
- /package/{utils → shared/utils}/timezone.ts +0 -0
- /package/{utils → shared/utils}/utils.ts +0 -0
package/.config/lint.js
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
// @ts-check
|
2
2
|
|
3
|
-
// @ts-ignore
|
4
3
|
import vueI18n from '@intlify/eslint-plugin-vue-i18n'
|
5
4
|
import eslintPluginCompat from 'eslint-plugin-compat'
|
6
5
|
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
@@ -9,7 +8,7 @@ import globals from 'globals'
|
|
9
8
|
import { createJiti } from 'jiti'
|
10
9
|
|
11
10
|
const jiti = createJiti(import.meta.url)
|
12
|
-
const constants = await jiti.import('../utils/constants.ts')
|
11
|
+
const constants = await jiti.import('../shared/utils/constants.ts')
|
13
12
|
// @ts-ignore
|
14
13
|
const POLYFILLS = constants.POLYFILLS
|
15
14
|
|
@@ -10,23 +10,19 @@
|
|
10
10
|
|
11
11
|
<script setup lang="ts">
|
12
12
|
interface Props {
|
13
|
-
ogImageAlt: string
|
14
13
|
ogImageComponent?: string
|
15
14
|
}
|
16
15
|
const props = withDefaults(defineProps<Props>(), {
|
17
16
|
ogImageComponent: undefined,
|
18
17
|
})
|
19
|
-
const ogImageAltProp = toRef(() => props.ogImageAlt)
|
20
|
-
const ogImageComponentProp = toRef(() => props.ogImageComponent)
|
21
18
|
|
22
19
|
const { $dayjs } = useNuxtApp()
|
23
|
-
const { locale } = useI18n()
|
24
|
-
const siteConfig = useSiteConfig()
|
20
|
+
const { locale, t } = useI18n()
|
25
21
|
|
26
22
|
const { loadingIds, indicateLoadingDone } = useLoadingDoneIndicator('app')
|
27
23
|
|
28
24
|
// methods
|
29
|
-
const
|
25
|
+
const initialize = () => {
|
30
26
|
$dayjs.locale(locale.value)
|
31
27
|
|
32
28
|
if (import.meta.client) {
|
@@ -49,22 +45,15 @@ onMounted(() => indicateLoadingDone())
|
|
49
45
|
|
50
46
|
// initialization
|
51
47
|
defineOgImageComponent(
|
52
|
-
|
48
|
+
props.ogImageComponent || 'NuxtSeo',
|
49
|
+
{},
|
53
50
|
{
|
54
|
-
|
55
|
-
},
|
56
|
-
{
|
57
|
-
alt: ogImageAltProp.value,
|
51
|
+
alt: t('globalSeoOgImageAlt'),
|
58
52
|
},
|
59
53
|
)
|
60
54
|
useAppLayout()
|
61
|
-
useFavicons()
|
62
55
|
usePolyfills()
|
63
|
-
useSchemaOrg([
|
64
|
-
defineWebSite({
|
65
|
-
description: siteConfig.description,
|
66
|
-
}),
|
67
|
-
])
|
56
|
+
useSchemaOrg([defineWebSite()])
|
68
57
|
useVioGtag()
|
69
|
-
|
58
|
+
initialize()
|
70
59
|
</script>
|
@@ -26,8 +26,6 @@
|
|
26
26
|
|
27
27
|
<script setup lang="ts">
|
28
28
|
import type { NuxtLinkProps } from '#app'
|
29
|
-
import type { I18N_LOCALE_CODE } from '../../../types/i18n'
|
30
|
-
import { append } from '../../../utils/utils' // TODO: wait for autoimport to be fixed and remove this import
|
31
29
|
|
32
30
|
interface Props {
|
33
31
|
ariaLabel?: string
|
@@ -0,0 +1,115 @@
|
|
1
|
+
export const useAppLayout = () => {
|
2
|
+
const appConfig = useAppConfig()
|
3
|
+
const colorMode = useColorMode()
|
4
|
+
const siteConfig = useSiteConfig()
|
5
|
+
|
6
|
+
if (import.meta.server) {
|
7
|
+
// style
|
8
|
+
useHeadSafe({
|
9
|
+
bodyAttrs: {
|
10
|
+
class:
|
11
|
+
'bg-background-bright dark:bg-background-dark text-text-dark dark:text-text-bright',
|
12
|
+
},
|
13
|
+
})
|
14
|
+
|
15
|
+
// favicon (https://vite-pwa-org.netlify.app/assets-generator/)
|
16
|
+
useServerHeadSafe({
|
17
|
+
link: [
|
18
|
+
{
|
19
|
+
href: `/site.webmanifest?v=${CACHE_VERSION}`,
|
20
|
+
rel: 'manifest',
|
21
|
+
},
|
22
|
+
{
|
23
|
+
href: `/favicon.ico?v=${CACHE_VERSION}`,
|
24
|
+
rel: 'icon',
|
25
|
+
sizes: '48x48',
|
26
|
+
},
|
27
|
+
{
|
28
|
+
href: `/assets/static/favicon/favicon.svg?v=${CACHE_VERSION}`,
|
29
|
+
rel: 'icon',
|
30
|
+
sizes: 'any',
|
31
|
+
type: 'image/svg+xml',
|
32
|
+
},
|
33
|
+
{
|
34
|
+
href: `/assets/static/favicon/apple-touch-icon-180x180.png?v=${CACHE_VERSION}`,
|
35
|
+
rel: 'apple-touch-icon',
|
36
|
+
},
|
37
|
+
],
|
38
|
+
})
|
39
|
+
|
40
|
+
// i18n
|
41
|
+
useHeadSafe(useLocaleHead().value)
|
42
|
+
}
|
43
|
+
|
44
|
+
if (import.meta.client) {
|
45
|
+
// theme
|
46
|
+
const updateThemeColor = () => {
|
47
|
+
useSeoMeta({
|
48
|
+
themeColor: appConfig.vio.themeColor, // colorMode.value === 'dark' ? THEME_COLOR_DARK : THEME_COLOR,
|
49
|
+
})
|
50
|
+
}
|
51
|
+
updateThemeColor()
|
52
|
+
watch(() => colorMode.value, updateThemeColor)
|
53
|
+
}
|
54
|
+
|
55
|
+
// seo
|
56
|
+
useSeoMeta({
|
57
|
+
titleTemplate: (title) =>
|
58
|
+
TITLE_TEMPLATE({
|
59
|
+
siteName: siteConfig.name,
|
60
|
+
title,
|
61
|
+
}),
|
62
|
+
})
|
63
|
+
}
|
64
|
+
|
65
|
+
export const useHeadDefault = (input: Parameters<typeof useSeoMeta>[0]) => {
|
66
|
+
const siteConfig = useSiteConfig()
|
67
|
+
|
68
|
+
const description =
|
69
|
+
toValue(input.description) || (siteConfig.description as string)
|
70
|
+
const title = TITLE_TEMPLATE({
|
71
|
+
siteName: siteConfig.name,
|
72
|
+
title: toValue(input.title)?.toString() || undefined,
|
73
|
+
})
|
74
|
+
|
75
|
+
useSeoMeta({
|
76
|
+
...(description
|
77
|
+
? {
|
78
|
+
description,
|
79
|
+
ogDescription: description,
|
80
|
+
twitterDescription: description,
|
81
|
+
}
|
82
|
+
: {}),
|
83
|
+
...(title ? { title, ogTitle: title, twitterTitle: title } : {}),
|
84
|
+
...input,
|
85
|
+
})
|
86
|
+
}
|
87
|
+
|
88
|
+
const POLYFILLS_URL = `https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=${POLYFILLS.join(
|
89
|
+
'%2C',
|
90
|
+
)}&flags=gated`
|
91
|
+
|
92
|
+
export const usePolyfills = () => {
|
93
|
+
if (!POLYFILLS.length) return
|
94
|
+
|
95
|
+
if (import.meta.server) {
|
96
|
+
useHead({
|
97
|
+
link: [
|
98
|
+
{
|
99
|
+
rel: 'preload',
|
100
|
+
href: POLYFILLS_URL,
|
101
|
+
crossorigin: 'anonymous',
|
102
|
+
as: 'script',
|
103
|
+
'data-testid': 'polyfill-preload',
|
104
|
+
},
|
105
|
+
],
|
106
|
+
script: [
|
107
|
+
{
|
108
|
+
src: POLYFILLS_URL,
|
109
|
+
crossorigin: 'anonymous',
|
110
|
+
'data-testid': 'polyfill-script',
|
111
|
+
},
|
112
|
+
],
|
113
|
+
})
|
114
|
+
}
|
115
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
export const useGetServiceHref = () => {
|
2
|
+
const host = useHost()
|
3
|
+
const runtimeConfig = useRuntimeConfig()
|
4
|
+
|
5
|
+
return ({
|
6
|
+
isSsr = true,
|
7
|
+
name,
|
8
|
+
port,
|
9
|
+
}: {
|
10
|
+
isSsr?: boolean
|
11
|
+
name?: string
|
12
|
+
port?: number
|
13
|
+
}) =>
|
14
|
+
getServiceHref({
|
15
|
+
host,
|
16
|
+
isSsr,
|
17
|
+
name,
|
18
|
+
port,
|
19
|
+
stagingHost: runtimeConfig.public.vio.stagingHost,
|
20
|
+
})
|
21
|
+
}
|
22
|
+
|
23
|
+
export const useHost = () => {
|
24
|
+
const { ssrContext } = useNuxtApp()
|
25
|
+
const host = ssrContext ? getHost(ssrContext.event) : location.host
|
26
|
+
|
27
|
+
if (!host) throw new Error('Host is not given!')
|
28
|
+
|
29
|
+
return host
|
30
|
+
}
|
@@ -24,7 +24,8 @@ const errorProp = toRef(() => props.error)
|
|
24
24
|
// initialization
|
25
25
|
useAppLayout()
|
26
26
|
|
27
|
-
|
27
|
+
useHeadDefault({
|
28
28
|
title: `${errorProp.value.statusCode} - ${errorProp.value.message}`,
|
29
29
|
})
|
30
|
+
defineOgImageComponent('NuxtSeo', {}, {})
|
30
31
|
</script>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<template>
|
2
|
+
<VioPageLegalNotice />
|
3
|
+
</template>
|
4
|
+
|
5
|
+
<script setup lang="ts">
|
6
|
+
const { t } = useI18n()
|
7
|
+
|
8
|
+
// data
|
9
|
+
const title = t('title')
|
10
|
+
|
11
|
+
// initialization
|
12
|
+
useHeadDefault({ title })
|
13
|
+
</script>
|
14
|
+
|
15
|
+
<i18n lang="yaml">
|
16
|
+
de:
|
17
|
+
title: Impressum
|
18
|
+
en:
|
19
|
+
title: Legal notice
|
20
|
+
</i18n>
|
@@ -35,23 +35,40 @@
|
|
35
35
|
log: true,
|
36
36
|
contactForm: true,
|
37
37
|
contactExternal: true,
|
38
|
-
comments: {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
},
|
44
|
-
},
|
45
|
-
newsletter: {
|
46
|
-
data: true,
|
47
|
-
},
|
48
|
-
pluginsTools: {
|
49
|
-
youTube: true,
|
50
|
-
googleWebFonts: true,
|
51
|
-
fontAwesome: true,
|
52
|
-
googleMaps: true,
|
53
|
-
googleReCaptcha: true,
|
38
|
+
// comments: {
|
39
|
+
// ip: true,
|
40
|
+
// subscribe: true,
|
41
|
+
// storageDuration: true,
|
42
|
+
// legalBasis: true,
|
43
|
+
// },
|
54
44
|
},
|
45
|
+
// newsletter: {
|
46
|
+
// data: true,
|
47
|
+
// },
|
48
|
+
// pluginsTools: {
|
49
|
+
// youTube: true,
|
50
|
+
// googleWebFonts: true,
|
51
|
+
// fontAwesome: true,
|
52
|
+
// googleMaps: true,
|
53
|
+
// googleReCaptcha: true,
|
54
|
+
// },
|
55
55
|
}"
|
56
56
|
/>
|
57
57
|
</template>
|
58
|
+
|
59
|
+
<script setup lang="ts">
|
60
|
+
const { t } = useI18n()
|
61
|
+
|
62
|
+
// data
|
63
|
+
const title = t('title')
|
64
|
+
|
65
|
+
// initialization
|
66
|
+
useHeadDefault({ title })
|
67
|
+
</script>
|
68
|
+
|
69
|
+
<i18n lang="yaml">
|
70
|
+
de:
|
71
|
+
title: Datenschutzerklärung
|
72
|
+
en:
|
73
|
+
title: Privacy Policy
|
74
|
+
</i18n>
|
package/i18n/i18n.config.ts
CHANGED
package/i18n/locales/de.json
CHANGED
package/i18n/locales/en.json
CHANGED
package/nuxt.config.ts
CHANGED
@@ -3,12 +3,12 @@ import { defu } from 'defu'
|
|
3
3
|
|
4
4
|
import {
|
5
5
|
SITE_URL,
|
6
|
-
|
6
|
+
VIO_SITE_NAME,
|
7
7
|
TIMEZONE_COOKIE_NAME,
|
8
8
|
GTAG_COOKIE_ID,
|
9
|
-
|
10
|
-
} from './utils/constants'
|
11
|
-
import { VIO_NUXT_BASE_CONFIG } from './utils/nuxt'
|
9
|
+
VIO_GET_CSP,
|
10
|
+
} from './shared/utils/constants'
|
11
|
+
import { VIO_NUXT_BASE_CONFIG } from './shared/utils/nuxt'
|
12
12
|
|
13
13
|
export default defineNuxtConfig(
|
14
14
|
defu(
|
@@ -18,7 +18,6 @@ export default defineNuxtConfig(
|
|
18
18
|
htmlAttrs: {
|
19
19
|
lang: 'en', // fallback data to prevent invalid html at generation
|
20
20
|
},
|
21
|
-
titleTemplate: '%s', // fully set in `composables/useAppLayout.ts`
|
22
21
|
},
|
23
22
|
pageTransition: {
|
24
23
|
name: 'layout',
|
@@ -40,6 +39,9 @@ export default defineNuxtConfig(
|
|
40
39
|
enabled: true,
|
41
40
|
},
|
42
41
|
},
|
42
|
+
future: {
|
43
|
+
compatibilityVersion: 4,
|
44
|
+
},
|
43
45
|
modules: [
|
44
46
|
'@dargmuesli/nuxt-cookie-control',
|
45
47
|
'@nuxt/devtools',
|
@@ -71,7 +73,7 @@ export default defineNuxtConfig(
|
|
71
73
|
"'unsafe-inline'", // nuxt-color-mode (https://github.com/nuxt-modules/color-mode/issues/266), runtimeConfig (static)
|
72
74
|
],
|
73
75
|
},
|
74
|
-
|
76
|
+
VIO_GET_CSP(SITE_URL),
|
75
77
|
nuxtConfigSecurityHeaders.contentSecurityPolicy,
|
76
78
|
)
|
77
79
|
}
|
@@ -120,6 +122,12 @@ export default defineNuxtConfig(
|
|
120
122
|
},
|
121
123
|
},
|
122
124
|
vite: {
|
125
|
+
optimizeDeps: {
|
126
|
+
include: [
|
127
|
+
'@dargmuesli/nuxt-cookie-control/runtime/types',
|
128
|
+
'@vuelidate/validators',
|
129
|
+
],
|
130
|
+
},
|
123
131
|
plugins: [tailwindcss()],
|
124
132
|
},
|
125
133
|
|
@@ -198,7 +206,7 @@ export default defineNuxtConfig(
|
|
198
206
|
initMode: 'manual',
|
199
207
|
},
|
200
208
|
htmlValidator: {
|
201
|
-
|
209
|
+
failOnError: true,
|
202
210
|
logLevel: 'warning',
|
203
211
|
},
|
204
212
|
i18n: {
|
@@ -247,7 +255,6 @@ export default defineNuxtConfig(
|
|
247
255
|
strict: true,
|
248
256
|
},
|
249
257
|
site: {
|
250
|
-
id: 'vio',
|
251
258
|
url: SITE_URL,
|
252
259
|
},
|
253
260
|
sitemap: {
|
@@ -309,7 +316,7 @@ export default defineNuxtConfig(
|
|
309
316
|
},
|
310
317
|
},
|
311
318
|
VIO_NUXT_BASE_CONFIG({
|
312
|
-
siteName:
|
319
|
+
siteName: VIO_SITE_NAME,
|
313
320
|
stagingHost: 'localhost:3000',
|
314
321
|
}),
|
315
322
|
),
|
package/package.json
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
{
|
2
2
|
"dependencies": {
|
3
|
-
"@dargmuesli/nuxt-cookie-control": "8.5.
|
3
|
+
"@dargmuesli/nuxt-cookie-control": "8.5.4",
|
4
4
|
"@eslint/compat": "1.2.7",
|
5
5
|
"@heroicons/vue": "2.2.0",
|
6
6
|
"@http-util/status-i18n": "0.9.0",
|
7
7
|
"@intlify/eslint-plugin-vue-i18n": "4.0.0",
|
8
|
-
"@nuxt/devtools": "2.
|
9
|
-
"@nuxt/eslint": "1.
|
10
|
-
"@nuxt/image": "1.
|
8
|
+
"@nuxt/devtools": "2.3.0",
|
9
|
+
"@nuxt/eslint": "1.2.0",
|
10
|
+
"@nuxt/image": "1.10.0",
|
11
11
|
"@nuxtjs/color-mode": "3.5.2",
|
12
12
|
"@nuxtjs/html-validator": "2.1.0",
|
13
|
-
"@nuxtjs/i18n": "9.2
|
14
|
-
"@nuxtjs/seo": "
|
13
|
+
"@nuxtjs/i18n": "9.3.2",
|
14
|
+
"@nuxtjs/seo": "3.0.1",
|
15
15
|
"@pinia/nuxt": "0.10.1",
|
16
16
|
"@tailwindcss/forms": "0.5.10",
|
17
17
|
"@tailwindcss/typography": "0.5.16",
|
18
|
-
"@tailwindcss/vite": "4.0.
|
18
|
+
"@tailwindcss/vite": "4.0.14",
|
19
19
|
"@types/lodash-es": "4.17.12",
|
20
20
|
"@urql/core": "5.1.1",
|
21
21
|
"@urql/vue": "1.4.3",
|
@@ -23,39 +23,37 @@
|
|
23
23
|
"@vuelidate/validators": "2.0.4",
|
24
24
|
"clipboardy": "4.0.0",
|
25
25
|
"dayjs": "2.0.0-alpha.4",
|
26
|
-
"eslint": "9.
|
27
|
-
"eslint-config-prettier": "10.
|
26
|
+
"eslint": "9.22.0",
|
27
|
+
"eslint-config-prettier": "10.1.1",
|
28
28
|
"eslint-plugin-compat": "6.0.2",
|
29
29
|
"eslint-plugin-prettier": "5.2.3",
|
30
30
|
"eslint-plugin-yml": "1.17.0",
|
31
31
|
"globals": "16.0.0",
|
32
32
|
"jiti": "2.4.2",
|
33
|
-
"jose": "6.0.
|
33
|
+
"jose": "6.0.10",
|
34
34
|
"nuxt-gtag": "3.0.2",
|
35
35
|
"nuxt-security": "2.2.0",
|
36
36
|
"sweetalert2": "11.17.2",
|
37
37
|
"vue-tsc": "2.2.8"
|
38
38
|
},
|
39
39
|
"devDependencies": {
|
40
|
-
"@unhead/vue": "1.11.20",
|
41
40
|
"@urql/devtools": "2.0.3",
|
42
41
|
"@urql/exchange-graphcache": "7.2.3",
|
43
|
-
"consola": "3.4.
|
42
|
+
"consola": "3.4.2",
|
44
43
|
"defu": "6.1.4",
|
45
44
|
"h3": "1.15.1",
|
46
45
|
"lodash-es": "4.17.21",
|
47
|
-
"nuxt": "3.
|
46
|
+
"nuxt": "3.16.1",
|
48
47
|
"pinia": "3.0.1",
|
49
48
|
"prettier": "3.5.3",
|
50
49
|
"prettier-plugin-tailwindcss": "0.6.11",
|
51
50
|
"serve": "14.2.4",
|
52
51
|
"sharp": "0.33.5",
|
53
|
-
"stylelint": "16.
|
52
|
+
"stylelint": "16.16.0",
|
54
53
|
"stylelint-config-recommended-vue": "1.6.0",
|
55
54
|
"stylelint-config-standard": "37.0.0",
|
56
55
|
"stylelint-no-unsupported-browser-features": "8.0.4",
|
57
|
-
"tailwindcss": "4.0.
|
58
|
-
"unhead": "1.11.20",
|
56
|
+
"tailwindcss": "4.0.14",
|
59
57
|
"vue": "3.5.13",
|
60
58
|
"vue-router": "4.5.0"
|
61
59
|
},
|
@@ -64,27 +62,17 @@
|
|
64
62
|
},
|
65
63
|
"files": [
|
66
64
|
".config",
|
67
|
-
"
|
68
|
-
"components",
|
69
|
-
"composables",
|
65
|
+
"app",
|
70
66
|
"i18n",
|
71
|
-
"layouts",
|
72
|
-
"pages",
|
73
|
-
"plugins",
|
74
67
|
"server",
|
75
|
-
"
|
76
|
-
"types",
|
77
|
-
"utils",
|
78
|
-
"app.config.ts",
|
79
|
-
"error.vue",
|
80
|
-
"i18n.config.ts",
|
68
|
+
"shared",
|
81
69
|
"nuxt.config.ts",
|
82
70
|
"package.json"
|
83
71
|
],
|
84
72
|
"main": "nuxt.config.ts",
|
85
73
|
"name": "@dargmuesli/nuxt-vio",
|
86
74
|
"peerDependencies": {
|
87
|
-
"nuxt": "3.
|
75
|
+
"nuxt": "3.16.0",
|
88
76
|
"vue": "3.5.13",
|
89
77
|
"vue-router": "4.5.0"
|
90
78
|
},
|
@@ -116,5 +104,5 @@
|
|
116
104
|
"start:static": "serve .playground/.output/public --ssl-cert ./.config/certificates/ssl.crt --ssl-key ./.config/certificates/ssl.key"
|
117
105
|
},
|
118
106
|
"type": "module",
|
119
|
-
"version": "
|
107
|
+
"version": "18.0.0"
|
120
108
|
}
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { defu } from 'defu'
|
2
2
|
import type { NuxtOptions } from 'nuxt/schema'
|
3
|
-
import { GET_CSP } from '../../utils/constants'
|
4
3
|
|
5
4
|
// remove invalid `'none'`s and duplicates
|
6
5
|
export const cleanupCsp = (
|
@@ -36,7 +35,7 @@ export default defineNitroPlugin((nitroApp) => {
|
|
36
35
|
defu(
|
37
36
|
{
|
38
37
|
headers: {
|
39
|
-
contentSecurityPolicy:
|
38
|
+
contentSecurityPolicy: VIO_GET_CSP(siteUrl),
|
40
39
|
},
|
41
40
|
},
|
42
41
|
routeRules['/**'],
|
@@ -17,5 +17,14 @@ export const useGetServiceHref = () => {
|
|
17
17
|
name,
|
18
18
|
port,
|
19
19
|
stagingHost: runtimeConfig.public.vio.stagingHost,
|
20
|
-
})
|
20
|
+
}).toString()
|
21
|
+
}
|
22
|
+
|
23
|
+
export const useHost = () => {
|
24
|
+
const event = useEvent()
|
25
|
+
const host = getHost(event)
|
26
|
+
|
27
|
+
if (!host) throw new Error('Host is not given!')
|
28
|
+
|
29
|
+
return host
|
21
30
|
}
|
package/server/utils/testing.ts
CHANGED
package/server/utils/timezone.ts
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
import type { H3Event } from 'h3'
|
2
2
|
|
3
|
-
import { TIMEZONE_COOKIE_NAME } from '../../utils/constants'
|
4
|
-
|
5
3
|
// TODO: rename to `getTimezone` (https://github.com/nuxt/cli/issues/266)
|
6
4
|
export const getTimezoneServer = async (event: H3Event) => {
|
7
5
|
const timezoneBySsr = event.context.$timezone
|
@@ -3,8 +3,7 @@ import { consola } from 'consola'
|
|
3
3
|
import { type H3Event, setCookie } from 'h3'
|
4
4
|
import { decodeJwt } from 'jose'
|
5
5
|
|
6
|
-
import { useVioAuthStore } from '
|
7
|
-
import { JWT_NAME } from './constants'
|
6
|
+
import { useVioAuthStore } from '../../app/stores/auth'
|
8
7
|
|
9
8
|
export const getJwtFromCookie = () => {
|
10
9
|
const cookie = useCookie(JWT_NAME())
|
@@ -2,19 +2,19 @@ import { DEFAULTS } from '@dargmuesli/nuxt-cookie-control/runtime/types'
|
|
2
2
|
import { helpers } from '@vuelidate/validators'
|
3
3
|
import { defu } from 'defu'
|
4
4
|
|
5
|
-
export const
|
5
|
+
export const VIO_SITE_NAME = 'Vio'
|
6
6
|
|
7
7
|
export const SITE_URL =
|
8
8
|
process.env.SITE_URL ||
|
9
9
|
process.env.NUXT_PUBLIC_SITE_URL ||
|
10
10
|
`https://${process.env.HOST || 'localhost'}:${process.env.PORT || '3000'}`
|
11
|
-
export const CACHE_VERSION = '
|
11
|
+
export const CACHE_VERSION = 'zeMtipb6C9'
|
12
12
|
export const COOKIE_CONTROL_CONSENT_COOKIE_NAME =
|
13
13
|
DEFAULTS.cookieNameIsConsentGiven
|
14
|
-
export const COOKIE_PREFIX =
|
14
|
+
export const COOKIE_PREFIX = VIO_SITE_NAME.toLocaleLowerCase()
|
15
15
|
export const COOKIE_SEPARATOR = '_'
|
16
16
|
export const FETCH_RETRY_AMOUNT = 3
|
17
|
-
export const
|
17
|
+
export const VIO_GET_CSP = (siteUrl: string) =>
|
18
18
|
defu(
|
19
19
|
{
|
20
20
|
// Cloudflare
|
@@ -108,7 +108,7 @@ export const GET_CSP = (siteUrl: string) =>
|
|
108
108
|
// nuxt
|
109
109
|
...(process.env.NODE_ENV === 'development'
|
110
110
|
? {
|
111
|
-
'frame-src': `${siteUrl}/__nuxt_devtools__/client
|
111
|
+
'frame-src': [`${siteUrl}/__nuxt_devtools__/client/`], // devtools
|
112
112
|
}
|
113
113
|
: {}),
|
114
114
|
'connect-src': [
|
@@ -167,7 +167,7 @@ export const REGEX_UUID =
|
|
167
167
|
/^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/
|
168
168
|
export const TESTING_COOKIE_NAME = 'vio_is-testing'
|
169
169
|
export const TIMEZONE_COOKIE_NAME = [COOKIE_PREFIX, 'tz'].join(COOKIE_SEPARATOR)
|
170
|
-
export const TIMEZONE_HEADER_KEY = `X-${
|
170
|
+
export const TIMEZONE_HEADER_KEY = `X-${VIO_SITE_NAME}-Timezone`
|
171
171
|
export const TITLE_TEMPLATE = ({
|
172
172
|
siteName,
|
173
173
|
title,
|
@@ -2,8 +2,6 @@ import type { CombinedError } from '@urql/core'
|
|
2
2
|
import type { H3Event } from 'h3'
|
3
3
|
import type { Ref } from 'vue'
|
4
4
|
|
5
|
-
import type { ApiData, BackendError } from '../types/api'
|
6
|
-
|
7
5
|
export const getApiDataDefault = (): ApiData =>
|
8
6
|
computed(() =>
|
9
7
|
reactive({
|
@@ -63,15 +61,16 @@ export const getCombinedErrorMessages = (
|
|
63
61
|
return errorMessages
|
64
62
|
}
|
65
63
|
|
66
|
-
export const
|
64
|
+
export const getRootHost = (host: string) => {
|
67
65
|
const hostParts = host.split('.')
|
66
|
+
const hostPartsLast = hostParts[hostParts.length - 1]
|
68
67
|
|
69
|
-
if (/^localhost(:[0-9]+)?$/.test(
|
70
|
-
return
|
68
|
+
if (hostPartsLast && /^localhost(:[0-9]+)?$/.test(hostPartsLast))
|
69
|
+
return hostPartsLast
|
71
70
|
|
72
71
|
if (hostParts.length === 1) return hostParts[0]
|
73
72
|
|
74
|
-
return `${hostParts[hostParts.length - 2]}.${
|
73
|
+
return `${hostParts[hostParts.length - 2]}.${hostPartsLast}`
|
75
74
|
}
|
76
75
|
|
77
76
|
export const getHost = (event: H3Event) => {
|
@@ -106,6 +105,6 @@ export const getServiceHref = ({
|
|
106
105
|
} else if (isSsr && process.server) {
|
107
106
|
return `http://${name}${portString}`
|
108
107
|
} else {
|
109
|
-
return `https://${nameSubdomainString}${
|
108
|
+
return `https://${nameSubdomainString}${getRootHost(host)}`
|
110
109
|
}
|
111
110
|
}
|
@@ -1,28 +0,0 @@
|
|
1
|
-
export const useAppLayout = () => {
|
2
|
-
const appConfig = useAppConfig()
|
3
|
-
const siteConfig = useSiteConfig()
|
4
|
-
|
5
|
-
useServerHeadSafe({
|
6
|
-
...useLocaleHead().value,
|
7
|
-
bodyAttrs: {
|
8
|
-
class:
|
9
|
-
'bg-background-bright dark:bg-background-dark text-text-dark dark:text-text-bright',
|
10
|
-
},
|
11
|
-
})
|
12
|
-
|
13
|
-
// adding `Server` leads incorrect title template on hydration
|
14
|
-
useSeoMeta({
|
15
|
-
titleTemplate: (title) =>
|
16
|
-
TITLE_TEMPLATE({
|
17
|
-
siteName: siteConfig.name,
|
18
|
-
title,
|
19
|
-
}),
|
20
|
-
})
|
21
|
-
|
22
|
-
if (appConfig.vio.themeColor) {
|
23
|
-
useServerSeoMeta({
|
24
|
-
msapplicationTileColor: appConfig.vio.themeColor,
|
25
|
-
themeColor: appConfig.vio.themeColor,
|
26
|
-
})
|
27
|
-
}
|
28
|
-
}
|
@@ -1,21 +0,0 @@
|
|
1
|
-
export const useFavicons = () => {
|
2
|
-
const appConfig = useAppConfig()
|
3
|
-
|
4
|
-
useServerHeadSafe({
|
5
|
-
link: [
|
6
|
-
{
|
7
|
-
href: `/site.webmanifest?v=${CACHE_VERSION}`,
|
8
|
-
rel: 'manifest',
|
9
|
-
},
|
10
|
-
{
|
11
|
-
color: appConfig.vio.themeColor,
|
12
|
-
href: `/assets/static/favicon/safari-pinned-tab.svg?v=${CACHE_VERSION}`,
|
13
|
-
rel: 'mask-icon',
|
14
|
-
},
|
15
|
-
{
|
16
|
-
href: `/favicon.ico?v=${CACHE_VERSION}`,
|
17
|
-
rel: 'shortcut icon',
|
18
|
-
},
|
19
|
-
],
|
20
|
-
})
|
21
|
-
}
|
@@ -1,25 +0,0 @@
|
|
1
|
-
import type { UseSeoMetaInput } from '@unhead/vue'
|
2
|
-
|
3
|
-
export const useHeadDefault = (input: UseSeoMetaInput) => {
|
4
|
-
const siteConfig = useSiteConfig()
|
5
|
-
|
6
|
-
const description = input.description || siteConfig.description
|
7
|
-
const title = TITLE_TEMPLATE({
|
8
|
-
siteName: siteConfig.name,
|
9
|
-
title: input.title?.toString(),
|
10
|
-
})
|
11
|
-
|
12
|
-
// can't be server side or it won't update on the client
|
13
|
-
useSeoMeta({
|
14
|
-
...(description
|
15
|
-
? {
|
16
|
-
description,
|
17
|
-
ogDescription: description,
|
18
|
-
twitterDescription: description,
|
19
|
-
}
|
20
|
-
: {}),
|
21
|
-
msapplicationConfig: `/assets/static/favicon/browserconfig.xml?v=${CACHE_VERSION}`,
|
22
|
-
...(title ? { title, ogTitle: title, twitterTitle: title } : {}),
|
23
|
-
...input,
|
24
|
-
})
|
25
|
-
}
|
package/composables/useHost.ts
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
import { POLYFILLS } from '../utils/constants'
|
2
|
-
|
3
|
-
export const usePolyfills = () => {
|
4
|
-
if (!POLYFILLS.length) return
|
5
|
-
|
6
|
-
const polyfillsUrl = `https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=${POLYFILLS.join(
|
7
|
-
'%2C',
|
8
|
-
)}&flags=gated`
|
9
|
-
|
10
|
-
useServerHead({
|
11
|
-
link: [
|
12
|
-
{
|
13
|
-
rel: 'preload',
|
14
|
-
href: polyfillsUrl,
|
15
|
-
crossorigin: 'anonymous',
|
16
|
-
as: 'script',
|
17
|
-
'data-testid': 'polyfill-preload',
|
18
|
-
},
|
19
|
-
],
|
20
|
-
script: [
|
21
|
-
{
|
22
|
-
src: polyfillsUrl,
|
23
|
-
crossorigin: 'anonymous',
|
24
|
-
'data-testid': 'polyfill-script',
|
25
|
-
},
|
26
|
-
],
|
27
|
-
})
|
28
|
-
}
|
package/pages/legal-notice.vue
DELETED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|