From 6d5eb0d02de1122273500c52e73fe8be70fde6c9 Mon Sep 17 00:00:00 2001 From: kiliman Date: Thu, 22 Sep 2022 14:19:05 -0500 Subject: [PATCH] feat: add support for multiple entries with same property name --- integration/meta-test.ts | 6 +++ packages/remix-react/components.tsx | 84 +++++++++++++---------------- 2 files changed, 42 insertions(+), 48 deletions(-) diff --git a/integration/meta-test.ts b/integration/meta-test.ts index 55157d3de8d..2d12e148f09 100644 --- a/integration/meta-test.ts +++ b/integration/meta-test.ts @@ -141,12 +141,18 @@ test.describe("meta array syntax", () => { json({ description: "This is a meta page", title: "Meta Page", + contentType: undefined, }); export const meta = ({ data }) => [ { key: "charset", content: "utf-8" }, { name: "description", content: data.description }, + { property: "og:image", content: "https://picsum.photos/300/300" }, + { property: "og:image:width", content: "300" }, + { property: "og:image:height", content: "300" }, { property: "og:image", content: "https://picsum.photos/200/200" }, + { property: "og:image", content: "https://picsum.photos/500/1000" }, + { property: "og:image:height", content: "1000" }, { property: "og:type", content: data.contentType }, // undefined { key: "httpEquiv:refresh", httpEquiv: "refresh", content: "3;url=https://www.mozilla.org" }, { title: data.title }, diff --git a/packages/remix-react/components.tsx b/packages/remix-react/components.tsx index 4913c6763b0..4792cc097fa 100644 --- a/packages/remix-react/components.tsx +++ b/packages/remix-react/components.tsx @@ -725,38 +725,21 @@ export function Meta() { return ( <> - {[...meta.entries()].map(([key, value]) => { - if (key === "title" && typeof value.content === "string") { - return {value.content}; + {Array.from(meta.entries()).map(([key, descriptor]) => { + let { name, property, content } = descriptor; + if (key === "title" && typeof content === "string") { + return {content}; } - if (key === "charset" && typeof value.content === "string") { - return ; + if (key === "charset" && typeof content === "string") { + return ; } - - if (name === "title") { - return {String(value)}; + if (property !== undefined) { + return ; } - - // Open Graph tags use the `property` attribute, while other meta tags - // use `name`. See https://ogp.me/ - let isOpenGraphTag = name.startsWith("og:"); - return [value].flat().map((content) => { - if (isOpenGraphTag) { - return ( - - ); - } - - if (typeof content === "string") { - return ; - } - - return ; - }); + if (name !== undefined) { + return ; + } + return ; })} ); @@ -770,9 +753,12 @@ export function processMeta( meta: MetaMap, routeMeta: HtmlMetaDescriptor | HtmlMetaDescriptor[] ) { + // normalize routeMeta to array format let items: HtmlMetaDescriptor[] = Array.isArray(routeMeta) ? routeMeta.map((item) => - item.title ? { key: "title", content: item.title } : item + item.title + ? { key: "title", content: item.title } + : { key: generateKey(item), ...item } ) : Object.entries(routeMeta) .map(([key, value]) => { @@ -789,14 +775,24 @@ export function processMeta( [propertyName]: key, content, })) - : { key, [propertyName]: key, content: value }; + : typeof value === "object" + ? { + key: `${key}.${(value as Record)?.content}`, + ...(value as Record), + } + : { + key: propertyName === "name" ? key : `${key}.${value}`, + [propertyName]: key, + content: assertString(value), + }; }) .flat(); - items.forEach((item) => { - let [key, value] = computeKey(item); - // child routes always override parent routes - meta.set(key, value); + // add items to the meta map by key (only add if content is defined) + items.forEach(({ key, ...rest }) => { + if (key && rest && rest.content) { + meta.set(key, rest); + } }); } @@ -808,22 +804,14 @@ function assertString(value: string | string[]): string { } function generateKey(item: HtmlMetaDescriptor) { - console.warn("No key provided to meta", item); + if (item.key) return item.key; + if (item.title) return "title"; + if (item.charset || item.charSet) return "charset"; + if (item.name) return item.name; + if (item.property) return `${item.property}.${item.content}`; return JSON.stringify(item); // generate a reasonable key } -function computeKey(item: HtmlMetaDescriptor): [string, HtmlMetaDescriptor] { - let { - name, - property, - title, - key = name ?? property ?? title ?? generateKey(item), - ...rest - } = item; - - return [key, { name, property, title, ...rest }]; -} - /** * Tracks whether Remix has finished hydrating or not, so scripts can be skipped * during client-side updates.