@dargmuesli/nuxt-vio 3.0.0-beta.1 → 3.0.0-beta.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. package/app.config.ts +32 -33
  2. package/components/{_ → vio/_}/VioApp.vue +22 -5
  3. package/components/{_ → vio/_}/VioError.vue +1 -1
  4. package/components/{_ → vio/_}/VioLink.vue +2 -2
  5. package/components/{form → vio/form}/VioForm.vue +2 -2
  6. package/components/{form → vio/form}/input/VioFormInput.vue +2 -2
  7. package/components/{layout → vio/layout}/VioLayout.vue +1 -1
  8. package/components/{layout → vio/layout}/VioLayoutFooter.vue +1 -1
  9. package/components/{layout → vio/layout}/VioLayoutFooterCategory.vue +1 -1
  10. package/components/{layout → vio/layout}/VioLayoutHeader.vue +1 -1
  11. package/components/{loader → vio/loader}/indicator/VioLoaderIndicator.vue +2 -2
  12. package/components/{loader → vio/loader}/indicator/VioLoaderIndicatorPing.vue +2 -2
  13. package/components/{page → vio/page}/VioPageLegalNotice.vue +9 -7
  14. package/components/{page → vio/page}/VioPagePrivacyPolicy.vue +18 -11
  15. package/composables/useAppLayout.ts +11 -17
  16. package/composables/useFavicons.ts +3 -31
  17. package/composables/useGetServiceHref.ts +2 -28
  18. package/composables/useHeadDefault.ts +13 -26
  19. package/composables/usePolyfills.ts +23 -0
  20. package/error.vue +2 -0
  21. package/locales/de.json +1 -1
  22. package/locales/en.json +1 -1
  23. package/nuxt.config.ts +19 -9
  24. package/package.json +21 -22
  25. package/plugins/dayjs.ts +6 -18
  26. package/plugins/gtag.client.ts +3 -0
  27. package/server/middleware/headers.ts +1 -1
  28. package/server/tsconfig.json +1 -1
  29. package/server/utils/util.ts +2 -0
  30. package/store/auth.ts +32 -0
  31. package/tailwind.config.ts +3 -5
  32. package/types/api.d.ts +9 -0
  33. package/types/fetch.d.ts +8 -0
  34. package/types/modules/gql.d.ts +6 -0
  35. package/types/modules/graphql.d.ts +6 -0
  36. package/utils/constants.ts +1 -0
  37. package/utils/networking.ts +44 -9
  38. package/LICENSE +0 -674
  39. package/composables/useHeadLayout.ts +0 -67
  40. /package/components/{button → vio/button}/VioButton.vue +0 -0
  41. /package/components/{button → vio/button}/VioButtonColored.vue +0 -0
  42. /package/components/{card → vio/card}/VioCard.vue +0 -0
  43. /package/components/{card → vio/card}/state/VioCardState.vue +0 -0
  44. /package/components/{card → vio/card}/state/VioCardStateAlert.vue +0 -0
  45. /package/components/{form → vio/form}/VioFormCheckbox.vue +0 -0
  46. /package/components/{form → vio/form}/input/VioFormInputIconWrapper.vue +0 -0
  47. /package/components/{form → vio/form}/input/VioFormInputUrl.vue +0 -0
  48. /package/components/{form → vio/form}/input/state/VioFormInputState.vue +0 -0
  49. /package/components/{form → vio/form}/input/state/VioFormInputStateError.vue +0 -0
  50. /package/components/{form → vio/form}/input/state/VioFormInputStateInfo.vue +0 -0
  51. /package/components/{icon → vio/icon}/IconArrowRight.vue +0 -0
  52. /package/components/{icon → vio/icon}/IconCalendar.vue +0 -0
  53. /package/components/{icon → vio/icon}/IconChatOutline.vue +0 -0
  54. /package/components/{icon → vio/icon}/IconChatSolid.vue +0 -0
  55. /package/components/{icon → vio/icon}/IconCheckCircle.vue +0 -0
  56. /package/components/{icon → vio/icon}/IconContainer.vue +0 -0
  57. /package/components/{icon → vio/icon}/IconDownload.vue +0 -0
  58. /package/components/{icon → vio/icon}/IconExclamationCircle.vue +0 -0
  59. /package/components/{icon → vio/icon}/IconHome.vue +0 -0
  60. /package/components/{icon → vio/icon}/IconHourglass.vue +0 -0
  61. /package/components/{icon → vio/icon}/IconLightbulb.vue +0 -0
  62. /package/components/{icon → vio/icon}/IconLogo.vue +0 -0
  63. /package/components/{icon → vio/icon}/IconMixcloud.vue +0 -0
  64. /package/components/{icon → vio/icon}/IconMusic.vue +0 -0
  65. /package/components/{icon → vio/icon}/IconPlay.vue +0 -0
  66. /package/components/{icon → vio/icon}/IconShare.vue +0 -0
  67. /package/components/{layout → vio/layout}/VioLayoutBreadcrumbs.vue +0 -0
  68. /package/components/{layout → vio/layout}/VioLayoutHr.vue +0 -0
  69. /package/components/{layout → vio/layout}/VioLayoutSpanList.vue +0 -0
  70. /package/components/{loader → vio/loader}/indicator/VioLoaderIndicatorSpinner.vue +0 -0
package/app.config.ts CHANGED
@@ -2,11 +2,8 @@ import { useServerSeoMeta } from '@unhead/vue'
2
2
 
3
3
  export default defineAppConfig({
4
4
  vio: {
5
- legalNotice: undefined,
6
- privacyPolicy: undefined,
7
- seoMeta: {
8
- twitterSite: '@dargmuesli',
9
- },
5
+ pages: undefined,
6
+ seoMeta: undefined,
10
7
  server: {
11
8
  middleware: {
12
9
  headers: {
@@ -37,55 +34,57 @@ export default defineAppConfig({
37
34
  },
38
35
  },
39
36
  },
40
- themeColor: '#202020',
37
+ themeColor: undefined,
41
38
  },
42
39
  })
43
40
 
44
41
  declare module 'nuxt/schema' {
45
- interface AppConfig {
42
+ interface AppConfigInput {
46
43
  vio: {
47
- legalNotice?: {
48
- contact: {
49
- email: string
50
- }
51
- responsibility: {
52
- address: {
53
- city: string
54
- name: string
55
- street: string
56
- }
57
- }
58
- tmg: {
59
- address: {
60
- city: string
61
- name: string
62
- street: string
44
+ pages?: {
45
+ legalNotice?: {
46
+ contact: {
47
+ email: string
63
48
  }
64
- }
65
- }
66
- privacyPolicy?: {
67
- hostingCdn?: {
68
- external: {
49
+ responsibility: {
69
50
  address: {
70
51
  city: string
71
52
  name: string
72
53
  street: string
73
54
  }
74
55
  }
75
- }
76
- mandatoryInfo?: {
77
- responsible: {
56
+ tmg: {
78
57
  address: {
79
58
  city: string
80
- email: string
81
59
  name: string
82
60
  street: string
83
61
  }
84
62
  }
85
63
  }
64
+ privacyPolicy?: {
65
+ hostingCdn?: {
66
+ external: {
67
+ address: {
68
+ city: string
69
+ name: string
70
+ street: string
71
+ }
72
+ }
73
+ }
74
+ mandatoryInfo?: {
75
+ responsible: {
76
+ address: {
77
+ city: string
78
+ email: string
79
+ name: string
80
+ street: string
81
+ }
82
+ }
83
+ }
84
+ }
86
85
  }
87
86
  seoMeta?: Parameters<typeof useServerSeoMeta>[0]
88
- server: {
87
+ server?: {
89
88
  middleware: {
90
89
  headers: {
91
90
  csp: {
@@ -3,15 +3,16 @@
3
3
  <NuxtLayout>
4
4
  <!-- `NuxtLayout` can't have mulitple child nodes (https://github.com/nuxt/nuxt/issues/21759) -->
5
5
  <div>
6
- <NuxtPage />
7
- <CookieControl :locale="locale as Locale" />
6
+ <NuxtPage :site-description="siteDescriptionProp" />
7
+ <CookieControl :locale="locale" />
8
8
  </div>
9
9
  </NuxtLayout>
10
10
  </div>
11
11
  </template>
12
12
 
13
13
  <script setup lang="ts">
14
- import { Locale } from '@dargmuesli/nuxt-cookie-control/dist/runtime/types'
14
+ import type { Locale } from '@dargmuesli/nuxt-cookie-control/dist/runtime/types'
15
+ import type { WritableComputedRef } from 'vue'
15
16
 
16
17
  export interface Props {
17
18
  ogImageAlt: string
@@ -25,13 +26,20 @@ const ogImageAltProp = toRef(() => props.ogImageAlt)
25
26
  const ogImageComponentProp = toRef(() => props.ogImageComponent)
26
27
  const siteDescriptionProp = toRef(() => props.siteDescription)
27
28
 
28
- const { locale } = useI18n()
29
+ const { $dayjs } = useNuxtApp()
30
+ const i18n = useI18n()
29
31
  const cookieControl = useCookieControl()
32
+ const siteConfig = useSiteConfig()
30
33
 
31
34
  const { loadingIds, indicateLoadingDone } = useLoadingDoneIndicator('app')
32
35
 
36
+ // data
37
+ const locale = i18n.locale as WritableComputedRef<Locale>
38
+
33
39
  // methods
34
40
  const init = () => {
41
+ $dayjs.locale(locale.value)
42
+
35
43
  if (process.client) {
36
44
  const cookieTimezone = useCookie(TIMEZONE_COOKIE_NAME, {
37
45
  // default: () => undefined, // setting `default` on the client side only does not write the cookie
@@ -63,7 +71,6 @@ watch(
63
71
  )
64
72
 
65
73
  // initialization
66
- init()
67
74
  updateSiteConfig({
68
75
  description: siteDescriptionProp.value,
69
76
  })
@@ -74,4 +81,14 @@ defineOgImage({
74
81
  })
75
82
  useAppLayout()
76
83
  useFavicons()
84
+ usePolyfills()
85
+ useSchemaOrg([
86
+ defineWebSite({
87
+ description: siteDescriptionProp,
88
+ inLanguage: locale,
89
+ name: siteConfig.name,
90
+ }),
91
+ defineWebPage(),
92
+ ])
93
+ init()
77
94
  </script>
@@ -3,7 +3,7 @@
3
3
  <div>
4
4
  {{ description }}
5
5
  </div>
6
- <div v-if="stack && !runtimeConfig.public.isInProduction" v-html="stack" />
6
+ <pre v-if="stack && !runtimeConfig.public.isInProduction" v-html="stack" />
7
7
  </template>
8
8
 
9
9
  <script setup lang="ts">
@@ -12,7 +12,7 @@
12
12
  >
13
13
  <slot />
14
14
  </a>
15
- <NuxtLink
15
+ <NuxtLinkLocale
16
16
  v-else
17
17
  :aria-label="ariaLabel"
18
18
  :class="classes"
@@ -20,7 +20,7 @@
20
20
  @click="emit('click')"
21
21
  >
22
22
  <slot />
23
- </NuxtLink>
23
+ </NuxtLinkLocale>
24
24
  </template>
25
25
 
26
26
  <script setup lang="ts">
@@ -9,7 +9,7 @@
9
9
  @submit="(e) => emit('submit', e)"
10
10
  >
11
11
  <VioCard class="flex flex-col" is-high>
12
- <div class="flex flex-col min-h-0 overflow-y-auto gap-6">
12
+ <div class="flex min-h-0 flex-col gap-6 overflow-y-auto">
13
13
  <slot />
14
14
  <div class="flex flex-col items-center justify-between">
15
15
  <VioButtonColored
@@ -43,7 +43,7 @@
43
43
  <script setup lang="ts">
44
44
  import type { BaseValidation } from '@vuelidate/core'
45
45
 
46
- import type { BackendError } from '~/../types/api'
46
+ import type { BackendError } from '../../../types/api'
47
47
 
48
48
  export interface Props {
49
49
  errors?: BackendError[]
@@ -53,7 +53,7 @@
53
53
  <VioFormInputIconWrapper v-if="validationProperty.$pending">
54
54
  <IconHourglass
55
55
  class="text-blue-600"
56
- :title="t('globalLoading')"
56
+ :title="t('globalStatusLoading')"
57
57
  />
58
58
  </VioFormInputIconWrapper>
59
59
  <VioFormInputIconWrapper
@@ -91,7 +91,7 @@
91
91
  <div class="md:w-2/3">
92
92
  <slot name="stateInfo" />
93
93
  <VioFormInputStateInfo v-if="value?.$pending">
94
- {{ t('globalLoading') }}
94
+ {{ t('globalStatusLoading') }}
95
95
  </VioFormInputStateInfo>
96
96
  </div>
97
97
  <div class="md:w-1/3" />
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="p-4 md:px-8">
2
+ <div class="container mx-auto p-4 md:px-8">
3
3
  <main>
4
4
  <slot />
5
5
  </main>
@@ -3,7 +3,7 @@
3
3
  <div class="flex flex-col gap-8">
4
4
  <div class="flex items-center">
5
5
  <VioLayoutHr />
6
- <IconLogo class="mx-12 h-12 w-12 brightness-0 opacity-60 invert" />
6
+ <IconLogo class="mx-12 h-12 w-12 opacity-60 brightness-0 invert" />
7
7
  <VioLayoutHr />
8
8
  </div>
9
9
  <!-- Justifying evenly, instead of "between", centers a single element. -->
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div
3
- class="flex flex-1 flex-col items-start p-4 basis-1/2 md:flex-none md:basis-auto gap-2"
3
+ class="flex flex-1 basis-1/2 flex-col items-start gap-2 p-4 md:flex-none md:basis-auto"
4
4
  >
5
5
  <span class="whitespace-nowrap text-lg font-medium leading-7">
6
6
  {{ heading }}
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <header class="flex items-center justify-between gap-4 mb-8">
2
+ <header class="mb-8 flex items-center justify-between gap-4">
3
3
  <VioButton :aria-label="t('creal')" :to="localePath('/')">
4
4
  <span class="text-lg font-bold">{{ t('creal') }}</span>
5
5
  <template #prefix>
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <div
3
3
  class="flex h-full items-center justify-center"
4
- :title="t('globalLoading')"
4
+ :title="t('globalStatusLoading')"
5
5
  >
6
- <div class="flex items-center justify-center w-1/2">
6
+ <div class="flex w-1/2 items-center justify-center">
7
7
  <slot />
8
8
  </div>
9
9
  </div>
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <VioLoaderIndicator>
3
3
  <div
4
- class="w-1/2 aspect-square animate-ping rounded-full bg-gray-500"
5
- :title="t('globalLoading')"
4
+ class="aspect-square w-1/2 animate-ping rounded-full bg-gray-500"
5
+ :title="t('globalStatusLoading')"
6
6
  />
7
7
  </VioLoaderIndicator>
8
8
  </template>
@@ -9,13 +9,13 @@
9
9
  <br />
10
10
  </template>
11
11
  <template #city>
12
- {{ appConfig.legalNotice.tmg.address.city }}
12
+ {{ appConfig.vio.pages.legalNotice.tmg.address.city }}
13
13
  </template>
14
14
  <template #name>
15
- {{ appConfig.legalNotice.tmg.address.name }}
15
+ {{ appConfig.vio.pages.legalNotice.tmg.address.name }}
16
16
  </template>
17
17
  <template #street>
18
- {{ appConfig.legalNotice.tmg.address.street }}
18
+ {{ appConfig.vio.pages.legalNotice.tmg.address.street }}
19
19
  </template>
20
20
  </i18n-t>
21
21
  </address>
@@ -24,7 +24,9 @@
24
24
  <p>
25
25
  <slot v-if="$slots.contactEmail" name="contactEmail" />
26
26
  <span v-else>
27
- {{ t('email', { email: appConfig.legalNotice.contact.email }) }}
27
+ {{
28
+ t('email', { email: appConfig.vio.pages.legalNotice.contact.email })
29
+ }}
28
30
  </span>
29
31
  </p>
30
32
 
@@ -36,13 +38,13 @@
36
38
  <br />
37
39
  </template>
38
40
  <template #city>
39
- {{ appConfig.legalNotice.responsibility.address.city }}
41
+ {{ appConfig.vio.pages.legalNotice.responsibility.address.city }}
40
42
  </template>
41
43
  <template #name>
42
- {{ appConfig.legalNotice.responsibility.address.name }}
44
+ {{ appConfig.vio.pages.legalNotice.responsibility.address.name }}
43
45
  </template>
44
46
  <template #street>
45
- {{ appConfig.legalNotice.responsibility.address.street }}
47
+ {{ appConfig.vio.pages.legalNotice.responsibility.address.street }}
46
48
  </template>
47
49
  </i18n-t>
48
50
  </address>
@@ -64,14 +64,21 @@
64
64
  <br />
65
65
  </template>
66
66
  <template #city>
67
- {{ appConfig.privacyPolicy.hostingCdn.external.address.city }}
67
+ {{
68
+ appConfig.vio.pages.privacyPolicy.hostingCdn.external
69
+ .address.city
70
+ }}
68
71
  </template>
69
72
  <template #name>
70
- {{ appConfig.privacyPolicy.hostingCdn.external.address.name }}
73
+ {{
74
+ appConfig.vio.pages.privacyPolicy.hostingCdn.external
75
+ .address.name
76
+ }}
71
77
  </template>
72
78
  <template #street>
73
79
  {{
74
- appConfig.privacyPolicy.hostingCdn.external.address.street
80
+ appConfig.vio.pages.privacyPolicy.hostingCdn.external
81
+ .address.street
75
82
  }}
76
83
  </template>
77
84
  </i18n-t>
@@ -109,29 +116,29 @@
109
116
  </template>
110
117
  <template #city>
111
118
  {{
112
- appConfig.privacyPolicy.mandatoryInfo.responsible.address
113
- .city
119
+ appConfig.vio.pages.privacyPolicy.mandatoryInfo.responsible
120
+ .address.city
114
121
  }}
115
122
  </template>
116
123
  <template #email>
117
124
  {{
118
125
  t('email', {
119
126
  email:
120
- appConfig.privacyPolicy.mandatoryInfo.responsible
121
- .address.email,
127
+ appConfig.vio.pages.privacyPolicy.mandatoryInfo
128
+ .responsible.address.email,
122
129
  })
123
130
  }}
124
131
  </template>
125
132
  <template #name>
126
133
  {{
127
- appConfig.privacyPolicy.mandatoryInfo.responsible.address
128
- .name
134
+ appConfig.vio.pages.privacyPolicy.mandatoryInfo.responsible
135
+ .address.name
129
136
  }}
130
137
  </template>
131
138
  <template #street>
132
139
  {{
133
- appConfig.privacyPolicy.mandatoryInfo.responsible.address
134
- .street
140
+ appConfig.vio.pages.privacyPolicy.mandatoryInfo.responsible
141
+ .address.street
135
142
  }}
136
143
  </template>
137
144
  </i18n-t>
@@ -1,5 +1,6 @@
1
1
  export const useAppLayout = () => {
2
2
  const appConfig = useAppConfig()
3
+ const siteConfig = useSiteConfig()
3
4
 
4
5
  useServerHeadSafe({
5
6
  ...useLocaleHead({ addSeoAttributes: true }).value,
@@ -7,23 +8,16 @@ export const useAppLayout = () => {
7
8
  class:
8
9
  'bg-background-bright dark:bg-background-dark font-sans text-text-dark dark:text-text-bright',
9
10
  },
10
- ...(appConfig.themeColor
11
- ? {
12
- meta: [
13
- {
14
- content: appConfig.themeColor,
15
- name: 'msapplication-TileColor',
16
- },
17
- {
18
- content: appConfig.themeColor,
19
- name: 'theme-color',
20
- },
21
- ],
22
- }
23
- : {}),
24
11
  })
25
12
 
26
- if (appConfig.seoMeta) {
27
- useServerSeoMeta(appConfig.seoMeta)
28
- }
13
+ useServerSeoMeta({
14
+ msapplicationTileColor: appConfig.vio.themeColor,
15
+ themeColor: appConfig.vio.themeColor,
16
+ titleTemplate: (titleChunk) => {
17
+ return titleChunk && titleChunk !== siteConfig.name
18
+ ? `${titleChunk} ${siteConfig.titleSeparator} ${siteConfig.name}`
19
+ : siteConfig.name
20
+ },
21
+ ...(appConfig.vio.seoMeta ? appConfig.vio.seoMeta : {}),
22
+ })
29
23
  }
@@ -4,46 +4,18 @@ export const useFavicons = () => {
4
4
  useServerHeadSafe({
5
5
  link: [
6
6
  {
7
- href: '/assets/static/favicon/apple-touch-icon.png?v=bOXMwoKlJr',
8
- rel: 'apple-touch-icon',
9
- sizes: '180x180',
10
- },
11
- {
12
- href: '/assets/static/favicon/favicon-16x16.png?v=bOXMwoKlJr',
13
- rel: 'icon',
14
- sizes: '16x16',
15
- type: 'image/png',
16
- },
17
- {
18
- href: '/assets/static/favicon/favicon-32x32.png?v=bOXMwoKlJr',
19
- rel: 'icon',
20
- sizes: '32x32',
21
- type: 'image/png',
22
- },
23
- {
24
- href: '/favicon.ico',
25
- rel: 'icon',
26
- type: 'image/x-icon',
27
- },
28
- {
29
- href: '/assets/static/favicon/site.webmanifest?v=bOXMwoKlJr',
7
+ href: `/assets/static/favicon/site.webmanifest?v=${CACHE_VERSION}`,
30
8
  rel: 'manifest',
31
9
  },
32
10
  {
33
11
  color: appConfig.vio.themeColor,
34
- href: '/assets/static/favicon/safari-pinned-tab.svg?v=bOXMwoKlJr',
12
+ href: `/assets/static/favicon/safari-pinned-tab.svg?v=${CACHE_VERSION}`,
35
13
  rel: 'mask-icon',
36
14
  },
37
15
  {
38
- href: '/favicon.ico?v=bOXMwoKlJr',
16
+ href: `/favicon.ico?v=${CACHE_VERSION}`,
39
17
  rel: 'shortcut icon',
40
18
  },
41
19
  ],
42
- meta: [
43
- {
44
- content: '/assets/static/favicon/browserconfig.xml?v=bOXMwoKlJr',
45
- name: 'msapplication-config',
46
- },
47
- ],
48
20
  })
49
21
  }
@@ -1,6 +1,6 @@
1
1
  export const useGetServiceHref = () => {
2
2
  const host = useHost()
3
- const config = useRuntimeConfig()
3
+ const runtimeConfig = useRuntimeConfig()
4
4
 
5
5
  return ({
6
6
  isSsr = true,
@@ -16,32 +16,6 @@ export const useGetServiceHref = () => {
16
16
  isSsr,
17
17
  name,
18
18
  port,
19
- stagingHost: config.public.stagingHost,
19
+ stagingHost: runtimeConfig.public.stagingHost,
20
20
  })
21
21
  }
22
-
23
- export const getServiceHref = ({
24
- host,
25
- isSsr = true,
26
- name,
27
- port,
28
- stagingHost,
29
- }: {
30
- host: string
31
- isSsr?: boolean
32
- name?: string
33
- port?: number
34
- stagingHost?: string
35
- }) => {
36
- const nameSubdomain = name?.replaceAll('_', '-')
37
- const nameSubdomainString = nameSubdomain ? `${nameSubdomain}.` : ''
38
- const portString = port ? `:${port}` : ''
39
-
40
- if (stagingHost) {
41
- return `https://${nameSubdomainString}${stagingHost}`
42
- } else if (isSsr && process.server) {
43
- return `http://${name}${portString}`
44
- } else {
45
- return `https://${nameSubdomainString}${getDomainTldPort(host)}`
46
- }
47
- }
@@ -1,34 +1,21 @@
1
1
  import { defu } from 'defu'
2
- import type { UseHeadSafeInput } from '@unhead/vue'
3
2
  import type { ComputedRef } from 'vue'
4
3
 
5
- export const useHeadDefault = (
6
- title: string | ComputedRef<string>,
7
- extension?: UseHeadSafeInput,
8
- ) => {
9
- const host = useHost()
10
- const router = useRouter()
4
+ export const useHeadDefault = ({
5
+ extension,
6
+ title,
7
+ }: {
8
+ extension?: Parameters<typeof useServerSeoMeta>[0]
9
+ title: string | ComputedRef<string>
10
+ }) => {
11
+ const attrs = useAttrs()
11
12
 
12
- const defaults: UseHeadSafeInput = {
13
- meta: [
14
- {
15
- id: 'og:title',
16
- property: 'og:title',
17
- content: title,
18
- },
19
- {
20
- id: 'og:url',
21
- property: 'og:url',
22
- content: `https://${host}${router.currentRoute.value.fullPath}`,
23
- },
24
- {
25
- id: 'twitter:title',
26
- property: 'twitter:title',
27
- content: title,
28
- },
29
- ],
13
+ const defaults: Parameters<typeof useServerSeoMeta>[0] = {
14
+ msapplicationConfig: `/assets/static/favicon/browserconfig.xml?v=${CACHE_VERSION}`,
30
15
  title,
16
+ twitterDescription: attrs['site-description'] as string,
17
+ twitterTitle: title,
31
18
  }
32
19
 
33
- return useServerHeadSafe(defu(extension, defaults))
20
+ useServerSeoMeta(defu(extension, defaults))
34
21
  }
@@ -0,0 +1,23 @@
1
+ export const usePolyfills = () => {
2
+ const polyfills =
3
+ 'https://polyfill.io/v3/polyfill.min.js?features=Promise&flags=gated'
4
+
5
+ useServerHead({
6
+ link: [
7
+ {
8
+ rel: 'preload',
9
+ href: polyfills,
10
+ crossorigin: 'anonymous',
11
+ as: 'script',
12
+ 'data-testid': 'polyfill-preload',
13
+ },
14
+ ],
15
+ script: [
16
+ {
17
+ src: polyfills,
18
+ crossorigin: 'anonymous',
19
+ 'data-testid': 'polyfill-script',
20
+ },
21
+ ],
22
+ })
23
+ }
package/error.vue CHANGED
@@ -18,6 +18,8 @@ export interface Props {
18
18
  const props = withDefaults(defineProps<Props>(), {})
19
19
  const errorProp = toRef(() => props.error)
20
20
 
21
+ // initialization
22
+ useAppLayout()
21
23
  useServerHeadSafe({
22
24
  title: `${errorProp.value.statusCode} - ${errorProp.value.message}`,
23
25
  })
package/locales/de.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "globalLoading": "Lade...",
3
2
  "globalPlaceholderUrl": "https://websei.te",
4
3
  "globalStatusError": "Fehler",
4
+ "globalStatusLoading": "Lade...",
5
5
  "globalValidationFailed": "Bitte überprüfe deine Eingaben 🙈",
6
6
  "globalValidationFormatUrlHttps": "Muss mit \"https://\" beginnen",
7
7
  "globalValidationLength": "Zu lang",
package/locales/en.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "globalLoading": "Loading...",
3
2
  "globalPlaceholderUrl": "https://websi.te",
4
3
  "globalStatusError": "Error",
4
+ "globalStatusLoading": "Loading...",
5
5
  "globalValidationFailed": "Please check your input 🙈",
6
6
  "globalValidationFormatUrlHttps": "Must start with \"https://\"",
7
7
  "globalValidationLength": "Too long",