-
Notifications
You must be signed in to change notification settings - Fork 10.3k
feat(gatsby): allow deduplicating head elements on id
#36138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5770973
1a327d5
a8c015a
2963da8
3157d10
1a6c5c5
83ec61d
a6a7820
35f358d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import headFunctionExportSharedData from "../../../shared-data/head-function-export.js" | ||
|
|
||
| it(`Deduplicates multiple tags with same id`, () => { | ||
| cy.visit(headFunctionExportSharedData.page.deduplication).waitForRouteChange() | ||
|
|
||
| // deduplication link has id and should be deduplicated | ||
| cy.get(`link[rel=deduplication]`).should("have.length", 1) | ||
| // last deduplication link should win | ||
| cy.get(`link[rel=deduplication]`).should("have.attr", "href", "/bar") | ||
| // we should preserve id | ||
| cy.get(`link[rel=deduplication]`).should( | ||
| "have.attr", | ||
| "id", | ||
| "deduplication-test" | ||
| ) | ||
|
|
||
| // alternate links are not using id, so should have multiple instances | ||
| cy.get(`link[rel=alternate]`).should("have.length", 2) | ||
| }) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import * as React from "react" | ||
|
|
||
| export default function HeadFunctionDeduplication() { | ||
| return ( | ||
| <> | ||
| <h1> | ||
| I deduplicated Head elements by their <code>id</code> | ||
| </h1> | ||
| </> | ||
| ) | ||
| } | ||
|
|
||
| function SEO({ children }) { | ||
| return ( | ||
| <> | ||
| <link rel="deduplication" id="deduplication-test" href="/foo" /> | ||
| <link | ||
| rel="alternate" | ||
| type="application/atom+xml" | ||
| title="RSS Feed" | ||
| href="/blog/news/atom" | ||
| /> | ||
| {children} | ||
| </> | ||
| ) | ||
| } | ||
|
|
||
| export function Head() { | ||
| return ( | ||
| <SEO> | ||
| <link rel="deduplication" id="deduplication-test" href="/bar" /> | ||
| <link rel="alternate" hrefLang="de-DE" href="/de/" /> | ||
| </SEO> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import headFunctionExportSharedData from "../../../shared-data/head-function-export.js" | ||
|
|
||
| it(`Deduplicates multiple tags with same id`, () => { | ||
| cy.visit(headFunctionExportSharedData.page.deduplication).waitForRouteChange() | ||
|
|
||
| // deduplication link has id and should be deduplicated | ||
| cy.get(`link[rel=deduplication]`).should("have.length", 1) | ||
| // last deduplication link should win | ||
| cy.get(`link[rel=deduplication]`).should("have.attr", "href", "/bar") | ||
| // we should preserve id | ||
| cy.get(`link[rel=deduplication]`).should( | ||
| "have.attr", | ||
| "id", | ||
| "deduplication-test" | ||
| ) | ||
|
|
||
| // alternate links are not using id, so should have multiple instances | ||
| cy.get(`link[rel=alternate]`).should("have.length", 2) | ||
| }) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import * as React from "react" | ||
|
|
||
| export default function HeadFunctionDeduplication() { | ||
| return ( | ||
| <> | ||
| <h1> | ||
| I deduplicated Head elements by their <code>id</code> | ||
| </h1> | ||
| </> | ||
| ) | ||
| } | ||
|
|
||
| function SEO({ children }) { | ||
| return ( | ||
| <> | ||
| <link rel="deduplication" id="deduplication-test" href="/foo" /> | ||
| <link | ||
| rel="alternate" | ||
| type="application/atom+xml" | ||
| title="RSS Feed" | ||
| href="/blog/news/atom" | ||
| /> | ||
| {children} | ||
| </> | ||
| ) | ||
| } | ||
|
|
||
| export function Head() { | ||
| return ( | ||
| <SEO> | ||
| <link rel="deduplication" id="deduplication-test" href="/bar" /> | ||
| <link rel="alternate" hrefLang="de-DE" href="/de/" /> | ||
| </SEO> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import * as React from "react" | ||
|
|
||
| export default function HeadFunctionDeduplication() { | ||
| return ( | ||
| <> | ||
| <h1> | ||
| I deduplicated Head elements by their <code>id</code> | ||
| </h1> | ||
| </> | ||
| ) | ||
| } | ||
|
|
||
| function SEO({ children }) { | ||
| return ( | ||
| <> | ||
| <link rel="deduplication" id="deduplication-test" href="/foo" /> | ||
| <link | ||
| rel="alternate" | ||
| type="application/atom+xml" | ||
| title="RSS Feed" | ||
| href="/blog/news/atom" | ||
| /> | ||
| {children} | ||
| </> | ||
| ) | ||
| } | ||
|
|
||
| export function Head() { | ||
| return ( | ||
| <SEO> | ||
| <link rel="deduplication" id="deduplication-test" href="/bar" /> | ||
| <link rel="alternate" hrefLang="de-DE" href="/de/" /> | ||
| </SEO> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,8 +54,10 @@ export function headHandlerForSSR({ | |
|
|
||
| const validHeadNodes = [] | ||
|
|
||
| const seenIds = new Map() | ||
| for (const node of headNodes) { | ||
| const { rawTagName, attributes } = node | ||
| const id = attributes.id | ||
|
|
||
| if (!VALID_NODE_NAMES.includes(rawTagName)) { | ||
| warnForInvalidTags(rawTagName) | ||
|
|
@@ -68,8 +70,17 @@ export function headHandlerForSSR({ | |
| }, | ||
| node.childNodes[0]?.textContent | ||
| ) | ||
|
|
||
| validHeadNodes.push(element) | ||
| if (id) { | ||
| if (!seenIds.has(id)) { | ||
| validHeadNodes.push(element) | ||
| seenIds.set(id, validHeadNodes.length - 1) | ||
| } else { | ||
| const indexOfPreviouslyInsertedNode = seenIds.get(id) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does the browser version include
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah that makes sense, saw all the other lines seemed duplicated 1 for 1 so wanted to double check. Thanks! |
||
| validHeadNodes[indexOfPreviouslyInsertedNode] = element | ||
| } | ||
| } else { | ||
| validHeadNodes.push(element) | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.