-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Import all missing front-end roadiz dependency files
- Loading branch information
1 parent
90a97aa
commit 577a846
Showing
16 changed files
with
473 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<script lang="ts" setup> | ||
import type { RoadizNodesSources, RoadizWalker } from '@roadiz/types' | ||
defineProps<{ | ||
blocks: RoadizWalker[] | ||
entity: RoadizNodesSources | ||
}>() | ||
</script> | ||
|
||
<template> | ||
<div :class="$style.root">{{ entity.title || 'VDefaultPage' }}</div> | ||
</template> | ||
|
||
<style lang="scss" module> | ||
.root { | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import type { RoadizAlternateLink } from '@roadiz/types' | ||
import type { LocaleObject } from '@nuxtjs/i18n' | ||
|
||
export function useAlternateLinks(links?: RoadizAlternateLink[]) { | ||
const alternateLinks = useState<RoadizAlternateLink[]>('alternateLinks', () => []) | ||
|
||
if (links) alternateLinks.value = links | ||
|
||
const { $i18n } = useNuxtApp() | ||
|
||
const availableAlternateLinks = computed(() => { | ||
const locales = | ||
($i18n.locales.value?.some((locale: unknown) => typeof locale === 'string') | ||
? ($i18n.locales.value as unknown as string[]) | ||
: ($i18n.locales.value as LocaleObject[]).map((locale) => locale.code)) || [] | ||
|
||
return alternateLinks.value.sort((a: RoadizAlternateLink, b: RoadizAlternateLink) => { | ||
const indexA = locales.includes(a.locale) ? locales.indexOf(a.locale) : 9999 | ||
const indexB = locales.includes(b.locale) ? locales.indexOf(b.locale) : 9999 | ||
|
||
return indexA - indexB | ||
}) | ||
}) | ||
|
||
return { alternateLinks, availableAlternateLinks } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import type { CommonContent, CommonContentMenuKey } from '~/types/api' | ||
import type { ValueOf } from '~/utils/types' | ||
|
||
export const COMMON_CONTENT_KEY = 'commonContent' | ||
|
||
export function useCommonContent() { | ||
const commonContent = useNuxtData<CommonContent>(COMMON_CONTENT_KEY).data | ||
const homeItem = computed(() => commonContent.value?.home) | ||
const head = computed(() => commonContent.value?.head) | ||
const errorWalker = computed(() => commonContent.value?.errorPage) | ||
|
||
function getMenu(key: CommonContentMenuKey): ValueOf<CommonContent['menus']> | undefined { | ||
return commonContent.value?.menus?.[key] | ||
} | ||
|
||
const mainMenuWalker = computed(() => getMenu('mainMenuWalker')) | ||
|
||
return { | ||
commonContent, | ||
head, | ||
homeItem, | ||
mainMenuWalker, | ||
errorWalker, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import type { Page } from '~/composables/use-page' | ||
|
||
export function useCurrentPage() { | ||
return useState<Page>('currentPage', () => ({})) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import { joinURL } from 'ufo' | ||
import type { RoadizAlternateLink, RoadizNodesSources, RoadizWebResponse } from '@roadiz/types' | ||
import type { Link, Script } from '@unhead/schema' | ||
import { COMMON_CONTENT_KEY, useCommonContent } from '~/composables/use-common-content' | ||
import { createGoogleTagManagerScript } from '~/utils/tracking/google-tag-manager' | ||
import { createMatomoTagManagerScript } from '~/utils/tracking/matomo-tag-manager' | ||
|
||
async function initI18n(locale?: string) { | ||
const nuxtApp = useNuxtApp() | ||
|
||
if (locale) { | ||
const { $i18n } = nuxtApp | ||
await $i18n.setLocale(locale) | ||
} else { | ||
// get the locale from the route (prefix) or cookie ? | ||
} | ||
} | ||
|
||
async function initCommonContent() { | ||
await useRoadizFetch('/common_content', { | ||
key: COMMON_CONTENT_KEY, | ||
}) | ||
} | ||
|
||
function initHead(webResponse?: RoadizWebResponse, alternateLinks?: RoadizAlternateLink[]) { | ||
const nuxtApp = useNuxtApp() | ||
const route = useRoute() | ||
const runtimeConfig = useRuntimeConfig() | ||
const { $i18n } = nuxtApp | ||
const script: (Script<['script']> | string)[] = [] | ||
const link: Link[] = [ | ||
{ | ||
rel: 'canonical', | ||
href: joinURL(runtimeConfig.public.site.url, webResponse?.item?.url || route.path), | ||
}, | ||
] | ||
|
||
// ALTERNATE LINKS | ||
const alternateLinksHead = alternateLinks?.map((alternateLink: RoadizAlternateLink) => { | ||
return { | ||
hid: `alternate-${alternateLink.locale}`, | ||
rel: 'alternate', | ||
hreflang: alternateLink.locale, | ||
href: joinURL(runtimeConfig.public.site.url, alternateLink.url), | ||
} | ||
}) | ||
if (alternateLinksHead) link.push(...alternateLinksHead) | ||
|
||
// GOOGLE TAG MANAGER | ||
// Google Tag Manager must not be loaded by tarteaucitron, it must configure tarteaucitron itself. | ||
// Notice: by using GTM you must comply with GDPR and cookie consent or just use | ||
// tarteaucitron with GA4, Matomo or Plausible | ||
const googleTagManager = runtimeConfig.public.googleTagManager | ||
if (googleTagManager && googleTagManager !== '') { | ||
script.push(createGoogleTagManagerScript(googleTagManager)) | ||
} | ||
|
||
// MATOMO | ||
const matomoURL = runtimeConfig.public.matomo?.url | ||
const matomoContainerID = runtimeConfig.public.matomo?.containerID | ||
if (matomoURL && matomoContainerID && matomoURL !== '' && matomoContainerID !== '') { | ||
script.push(createMatomoTagManagerScript(matomoContainerID, matomoURL)) | ||
} | ||
|
||
useHead({ | ||
htmlAttrs: { | ||
lang: $i18n.locale.value, | ||
}, | ||
script, | ||
link, | ||
meta: [ | ||
// app version | ||
{ name: 'version', content: runtimeConfig.public.version }, | ||
], | ||
}) | ||
} | ||
|
||
function initSeoMeta(webResponse?: RoadizWebResponse) { | ||
const nuxtApp = useNuxtApp() | ||
const { commonContent } = useCommonContent() | ||
const runtimeConfig = useRuntimeConfig() | ||
const head = webResponse?.head | ||
const description = webResponse?.head?.metaDescription || commonContent.value?.head?.metaDescription | ||
const title = webResponse?.head?.metaTitle || commonContent.value?.head?.metaTitle | ||
const siteName = commonContent.value?.head?.siteName || (nuxtApp.$config.siteName as string) || '' | ||
const { isActive: previewIsActive } = useRoadizPreview() | ||
const img = useImage() | ||
const image = () => { | ||
const image = | ||
head?.shareImage?.relativePath || | ||
// @ts-ignore not sure the `images` property exists, but generally it does | ||
head?.images?.[0]?.relativePath || | ||
// @ts-ignore not sure the `image` property exists, but generally it does | ||
head?.image?.[0]?.relativePath || | ||
commonContent.value?.head?.shareImage?.relativePath | ||
|
||
if (image) { | ||
return img(image, { | ||
width: 1200, | ||
quality: 70, | ||
}) | ||
} else { | ||
return joinURL(runtimeConfig.public.site.url, '/images/share.jpg') | ||
} | ||
} | ||
|
||
useServerSeoMeta({ | ||
description, | ||
ogTitle: title, | ||
ogSiteName: siteName, | ||
ogDescription: description, | ||
ogImage: image(), | ||
twitterCard: 'summary', | ||
twitterTitle: title, | ||
twitterDescription: description, | ||
robots: { | ||
noindex: (webResponse?.item as RoadizNodesSources)?.noIndex || previewIsActive.value, | ||
}, | ||
}) | ||
} | ||
|
||
export default defineNuxtPlugin(async () => { | ||
const route = useRoute() | ||
const isWildCardRoute = route.name === 'slug' | ||
const data = isWildCardRoute ? await useRoadizWebResponse() : undefined | ||
const locale = data && ((data.item as RoadizNodesSources)?.translation?.locale || undefined) | ||
|
||
if (locale) { | ||
// Set currentPage data accessible outside pages | ||
useCurrentPage().value = { | ||
webResponse: data.webResponse, | ||
alternateLinks: data.alternateLinks, | ||
} | ||
|
||
await initI18n(locale) | ||
useAlternateLinks(data?.alternateLinks) | ||
} | ||
await initCommonContent() | ||
initHead(data?.webResponse, data?.alternateLinks) | ||
initSeoMeta(data?.webResponse) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import type { RoadizAlternateLink, RoadizNodesSources, RoadizNodesSourcesHead, RoadizWebResponse } from '@roadiz/types' | ||
import type { MenuNodeType } from '~/types/app' | ||
import type { NSFooter, NSMenu, NSPage } from '~/types/roadiz' | ||
import type { RoadizWalkerKnown } from '~/utils/types' | ||
|
||
interface HydraError { | ||
'@context': string | ||
'@type': string | ||
'hydra:title': string | ||
'hydra:description': string | ||
message?: string | ||
trace: Array<HydraErrorTraceItem> | ||
} | ||
|
||
interface HydraErrorTraceItem { | ||
file: string | ||
line: number | ||
function: string | ||
class: string | ||
type: string | ||
args: Array<string> | ||
} | ||
|
||
interface PageResponse { | ||
webResponse: RoadizWebResponse | undefined | ||
alternateLinks?: RoadizAlternateLink[] | ||
locale?: string | ||
} | ||
|
||
type CommonContentMenuKey = 'mainMenuWalker' | 'footerMenuWalker' | 'headerMenuWalker' | string | ||
|
||
interface CommonContent { | ||
home?: RoadizNodesSources | ||
head?: RoadizNodesSourcesHead | ||
menus?: Record<CommonContentMenuKey, RoadizWalkerKnown<NSMenu, MenuNodeType>> | ||
errorPage?: RoadizWalkerKnown<NSPage> | ||
} | ||
|
||
interface CustomForm extends JsonLdObject { | ||
slug?: boolean | ||
name?: boolean | ||
open?: boolean | ||
definitionUrl?: string | null | ||
postUrl?: string | null | ||
description?: string | null | ||
color?: string | null | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import type { RoadizWalker, RoadizWebResponseBlocks } from '@roadiz/types' | ||
import { getArrayFromCollection } from '~/utils/roadiz/get-array-from-collection' | ||
|
||
// we have to get a hydra collection of RoadizWalker (JSON LD format), | ||
// because if the API has been requested as JSON format then we won't be able to parse the result (lack of '@type' properties) | ||
export function getBlockCollection(blocks: RoadizWebResponseBlocks): RoadizWalker[] { | ||
return getArrayFromCollection<RoadizWalker>(blocks) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import type { JsonLdObject } from '@roadiz/types' | ||
|
||
export function isNodeType(entity: unknown): entity is JsonLdObject { | ||
return !!(entity && typeof entity === 'object' && '@id' in entity && '@type' in entity) | ||
} | ||
|
||
export function isEntityType(entity: JsonLdObject, type: string): boolean { | ||
const regex = new RegExp('^(NS)?' + type + '$', 'gi') | ||
const matches = entity['@type']?.match(regex) | ||
return matches !== null && matches.length > 0 | ||
} | ||
|
||
export function isSchemaOrgType(entity: JsonLdObject, type: string): boolean { | ||
const regex = new RegExp('^(?:https?:\\/\\/schema\\.org\\/)?' + type + '$', 'gi') | ||
const matches = entity['@type']?.match(regex) | ||
return matches !== null && matches.length > 0 | ||
} | ||
|
||
export function isPageEntity(entity: JsonLdObject): boolean { | ||
return isEntityType(entity, 'Page') | ||
} | ||
|
||
export function isBlogPostEntity(entity: JsonLdObject): boolean { | ||
return isEntityType(entity, 'BlogPost') | ||
} | ||
|
||
export function isBlogListingEntity(entity: JsonLdObject): boolean { | ||
return isEntityType(entity, 'BlogPostContainer') | ||
} | ||
|
||
// BLOCKS | ||
|
||
export function isContentBlock(entity: JsonLdObject): boolean { | ||
return isEntityType(entity, 'ContentBlock') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import type { HydraCollection, JsonLdObject } from '@roadiz/types' | ||
|
||
export function getArrayFromCollection<T>( | ||
collection: HydraCollection<T> | Array<Omit<T, keyof JsonLdObject>> | unknown[], | ||
): T[] { | ||
if (Array.isArray(collection)) return collection as T[] | ||
|
||
return 'hydra:member' in collection && Array.isArray(collection['hydra:member']) ? collection['hydra:member'] : [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* @deprecated Use tarteaucitron for better GDPR integration | ||
* @see https://developers.google.com/analytics/devguides/collection/gtagjs | ||
* @param id | ||
*/ | ||
export function createGoogleAnalytics4Script(id: string): string { | ||
return ` | ||
window.dataLayer = window.dataLayer || []; | ||
function gtag(){dataLayer.push(arguments);} | ||
gtag('js', new Date()); | ||
gtag('config', '${id}'); | ||
` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* @see https://developers.google.com/tag-platform/tag-manager/web | ||
* @param id | ||
*/ | ||
export function createGoogleTagManagerScript(id: string): string { | ||
return ` | ||
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': | ||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], | ||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= | ||
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); | ||
})(window,document,'script','dataLayer','${id}'); | ||
` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* @see https://developer.matomo.org/guides/tagmanager/embedding | ||
* @param {string} id | ||
* @param {string} matomoTagManagerUrl | ||
*/ | ||
export function createMatomoTagManagerScript(id: string, matomoTagManagerUrl: string): string { | ||
return ` | ||
var _mtm = window._mtm = window._mtm || []; | ||
_mtm.push({'mtm.startTime': (new Date().getTime()), 'event': 'mtm.Start'}); | ||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; | ||
g.async=true; g.src='${matomoTagManagerUrl}/js/container_${id}.js'; s.parentNode.insertBefore(g,s); | ||
` | ||
} |
Oops, something went wrong.