From 029b0809525eced3d325b2d6dcc9eda257ce93b8 Mon Sep 17 00:00:00 2001 From: Manuel Odelain Date: Fri, 15 Mar 2024 14:08:11 +0100 Subject: [PATCH] feat(roadiz): add useRoadizWebResponse() --- composables/use-roadiz-web-response.ts | 31 ++++++++++++++++++++ utils/index.ts | 6 ++++ utils/roadiz/get-response-alternate-links.ts | 23 +++++++++++++++ utils/string/b64-decode-unicode.ts | 22 ++++++++++++++ 4 files changed, 82 insertions(+) create mode 100644 composables/use-roadiz-web-response.ts create mode 100644 utils/index.ts create mode 100644 utils/roadiz/get-response-alternate-links.ts create mode 100644 utils/string/b64-decode-unicode.ts diff --git a/composables/use-roadiz-web-response.ts b/composables/use-roadiz-web-response.ts new file mode 100644 index 0000000..1b34093 --- /dev/null +++ b/composables/use-roadiz-web-response.ts @@ -0,0 +1,31 @@ +import type { RoadizWebResponse } from '@roadiz/types' + +export async function useRoadizWebResponse(path: string) { + const fetch = useRoadizFetchFactory() + const { data } = await useAsyncData(async () => { + try { + const response = await fetch.raw('/web_response_by_path', { + method: 'GET', + query: { + path, + }, + }) + const headersLink = response.headers.get('link') + const alternateLinks = headersLink ? getResponseAlternateLinks(headersLink) : [] + + return { webResponse: response._data, alternateLinks } + } catch (error) { + console.error('Error=', error) + + return { error } + } + }) + const webResponse = data.value?.webResponse + + return { + alternateLinks: data.value?.alternateLinks || [], + webResponse, + item: webResponse?.item as T | undefined, + error: data.value?.error, + } +} diff --git a/utils/index.ts b/utils/index.ts new file mode 100644 index 0000000..73a15f0 --- /dev/null +++ b/utils/index.ts @@ -0,0 +1,6 @@ +// Enable auto import for all files nested into folders +// @see https://nuxt.com/docs/guide/directory-structure/composables#how-files-are-scanned +// string +export { b64DecodeUnicode } from './string/b64-decode-unicode' +// Roadiz +export { getResponseAlternateLinks } from './roadiz/get-response-alternate-links' diff --git a/utils/roadiz/get-response-alternate-links.ts b/utils/roadiz/get-response-alternate-links.ts new file mode 100644 index 0000000..840372c --- /dev/null +++ b/utils/roadiz/get-response-alternate-links.ts @@ -0,0 +1,23 @@ +import type { RoadizAlternateLink } from '@roadiz/types' + +export function getResponseAlternateLinks(links: string): Array { + return links + .split(',') + .filter((link: string) => { + return link + .split(';') + .map((attribute) => attribute.trim()) + .includes('type="text/html"') + }) + .map((link: string) => { + const attributes = link.split(';') + const title = attributes[3]?.split('title="').join('').split('"').join('').trim() || undefined + + return { + url: attributes[0].split('<').join('').split('>').join('').trim(), + locale: attributes[2].split('hreflang="').join('').split('"').join('').trim(), + // Must decode translation name from base64 because headers are ASCII only + title: title ? b64DecodeUnicode(title) : undefined, + } as RoadizAlternateLink + }) +} diff --git a/utils/string/b64-decode-unicode.ts b/utils/string/b64-decode-unicode.ts new file mode 100644 index 0000000..c9024d1 --- /dev/null +++ b/utils/string/b64-decode-unicode.ts @@ -0,0 +1,22 @@ +/* + * Decode base64 string to UTF-8 string on client-side and Node.js + */ +export function b64DecodeUnicode(str: string) { + if (!process.server) { + return decodeURIComponent( + Array.prototype.map + .call(window.atob(str), function (c: string) { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) + }) + .join(''), + ) + } + + return decodeURIComponent( + Array.prototype.map + .call(Buffer.from(str, 'base64').toString('binary'), function (c: string) { + return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) + }) + .join(''), + ) +}