@@ -2,6 +2,7 @@ import { css } from '@emotion/react';
22import { headlineMedium17 , space } from '@guardian/source/foundations' ;
33import { type ReactNode } from 'react' ;
44import sanitise , { type IOptions } from 'sanitize-html' ;
5+ import { isSkimlink } from '../lib/affiliateLinksUtils' ;
56import { getAttrs , parseHtml } from '../lib/domUtils' ;
67import { palette } from '../palette' ;
78
@@ -38,6 +39,7 @@ const renderTextElement = (node: Node, key: number): ReactNode => {
3839 return text === '' ? null : < em key = { key } > { children } </ em > ;
3940 case 'A' : {
4041 const attrs = getAttrs ( node ) ;
42+ const href = attrs ?. getNamedItem ( 'href' ) ?. value ;
4143
4244 return (
4345 < a
@@ -51,7 +53,7 @@ const renderTextElement = (node: Node, key: number): ReactNode => {
5153 ${ palette ( '--article-link-border-hover' ) } ;
5254 }
5355 ` }
54- href = { attrs ?. getNamedItem ( ' href' ) ?. value }
56+ href = { href }
5557 target = { attrs ?. getNamedItem ( 'target' ) ?. value }
5658 data-link-name = {
5759 attrs ?. getNamedItem ( 'data-link-name' ) ?. value
@@ -60,6 +62,15 @@ const renderTextElement = (node: Node, key: number): ReactNode => {
6062 attrs ?. getNamedItem ( 'data-component' ) ?. value
6163 }
6264 key = { key }
65+ /**
66+ * Affiliate links must have the rel attribute set to "sponsored"
67+ * @see https://developers.google.com/search/docs/crawling-indexing/qualify-outbound-links
68+ */
69+ rel = {
70+ isSkimlink ( href )
71+ ? getAttrs ( node ) ?. getNamedItem ( 'rel' ) ?. value
72+ : undefined
73+ }
6374 >
6475 { children }
6576 </ a >
0 commit comments