Skip to content

Commit d05f453

Browse files
committed
feat(utilities): markedSetNofollowLinks with hostname check
1 parent 6b8d271 commit d05f453

File tree

2 files changed

+53
-4
lines changed

2 files changed

+53
-4
lines changed

packages/utilities/src/utilities.client.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,23 @@ export function normalizeUrl(url: string, keepFragment?: boolean) {
159159

160160
// Helper function for markdown rendered marked
161161
// Renders links outside apify.com in readme with rel="noopener noreferrer nofollow" and target="_blank" attributes
162-
export function markedSetNofollowLinks(href: string, title: string, text: string) {
162+
export function markedSetNofollowLinks(href: string, title: string, text: string, hostname?: string) {
163163
let urlParsed: URL;
164164
try {
165165
urlParsed = new URL(href);
166166
} catch (e) {
167167
// Probably invalid url, go on
168168
}
169169
const isApifyLink = (urlParsed! && /(\.|^)apify\.com$/i.test(urlParsed.hostname));
170-
return (isApifyLink)
171-
? `<a href="${href}">${title || text}</a>`
172-
: `<a rel="noopener noreferrer nofollow" target="_blank" href="${href}">${title || text}</a>`;
170+
const isSameHostname = !hostname || (urlParsed! && urlParsed.hostname === hostname);
171+
172+
if (isApifyLink && isSameHostname) {
173+
return `<a href="${href}">${title || text}</a>`;
174+
} if (isApifyLink) {
175+
return `<a rel="noopener noreferrer" target="_blank" href="${href}">${title || text}</a>`;
176+
}
177+
178+
return `<a rel="noopener noreferrer nofollow" target="_blank" href="${href}">${title || text}</a>`;
173179
}
174180

175181
// Helper function for markdown rendered marked

test/utilities.client.test.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
isBadForMongo,
77
jsonStringifyExtended,
88
JsonVariable,
9+
markedSetNofollowLinks,
910
normalizeUrl,
1011
splitFullName,
1112
traverseObject,
@@ -1203,4 +1204,46 @@ describe('utilities.client', () => {
12031204
expect(splitFullName('More Spaces Between')).toEqual(['More', 'Spaces Between']);
12041205
});
12051206
});
1207+
1208+
describe('#markedSetNofollowLinks', () => {
1209+
it('should return a link without rel or target attributes for Apify links on the same hostname', () => {
1210+
const result = markedSetNofollowLinks('https://console.apify.com', 'Apify console', 'Apify Link', 'console.apify.com');
1211+
expect(result).toBe('<a href="https://console.apify.com">Apify console</a>');
1212+
});
1213+
1214+
it('should return a link with rel="noopener noreferrer" and target="_blank" for Apify links on a different hostname', () => {
1215+
const result = markedSetNofollowLinks('https://www.apify.com', 'Apify', 'Apify Link', 'different-hostname.com');
1216+
expect(result).toBe('<a rel="noopener noreferrer" target="_blank" href="https://www.apify.com">Apify</a>');
1217+
});
1218+
1219+
it('should return a link with rel="noopener noreferrer nofollow" and target="_blank" for non-Apify links', () => {
1220+
const result = markedSetNofollowLinks('https://www.example.com', 'Example', 'Example Link');
1221+
expect(result).toBe('<a rel="noopener noreferrer nofollow" target="_blank" href="https://www.example.com">Example</a>');
1222+
});
1223+
1224+
it('should return a link with rel="noopener noreferrer nofollow" and target="_blank" for invalid URLs', () => {
1225+
const result = markedSetNofollowLinks('invalid-url', 'Invalid', 'Invalid Link');
1226+
expect(result).toBe('<a rel="noopener noreferrer nofollow" target="_blank" href="invalid-url">Invalid</a>');
1227+
});
1228+
1229+
it('should handle a missing title and use the text instead', () => {
1230+
const result = markedSetNofollowLinks('https://www.apify.com', '', 'Apify Link', 'www.apify.com');
1231+
expect(result).toBe('<a href="https://www.apify.com">Apify Link</a>');
1232+
});
1233+
1234+
it('should handle a missing hostname parameter', () => {
1235+
const result = markedSetNofollowLinks('https://www.apify.com', 'Apify', 'Apify Link');
1236+
expect(result).toBe('<a href="https://www.apify.com">Apify</a>');
1237+
});
1238+
1239+
it('should treat subdomains of apify.com as Apify links', () => {
1240+
const result = markedSetNofollowLinks('https://docs.apify.com', 'Docs', 'Docs Link');
1241+
expect(result).toBe('<a href="https://docs.apify.com">Docs</a>');
1242+
});
1243+
1244+
it('should apply rel="noopener noreferrer nofollow" for links with an undefined hostname and non-Apify URLs', () => {
1245+
const result = markedSetNofollowLinks('https://example.com', 'Example', 'Example Link', undefined);
1246+
expect(result).toBe('<a rel="noopener noreferrer nofollow" target="_blank" href="https://example.com">Example</a>');
1247+
});
1248+
});
12061249
});

0 commit comments

Comments
 (0)