Skip to content

Commit 46b2713

Browse files
authored
[Docs Site] Only show external link arrow if element has no image children (#20998)
* [Docs Site] Only show external link arrow if element has no image children * unused import
1 parent ac90759 commit 46b2713

File tree

6 files changed

+50
-16
lines changed

6 files changed

+50
-16
lines changed

src/plugins/rehype/external-links.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
11
import rehypeExternalLinks, { type Options } from "rehype-external-links";
2+
import type { Element } from "hast";
3+
4+
function hasImgChild(node: Element): boolean {
5+
return node.children.some(
6+
(child) => child.type === "element" && child.tagName === "img",
7+
);
8+
}
9+
10+
export const externalLinkArrow = " ↗";
211

312
export const rehypeExternalLinksOptions = {
4-
content: {
5-
type: "text",
6-
value: " ↗",
13+
content: (element) => {
14+
if (!hasImgChild(element)) {
15+
return {
16+
type: "text",
17+
value: externalLinkArrow,
18+
};
19+
}
720
},
821
contentProperties: {
922
class: "external-link",

src/plugins/rehype/heading-slugs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { toString } from "hast-util-to-string";
22
import { visit } from "unist-util-visit";
33
import GithubSlugger from "github-slugger";
4-
import { rehypeExternalLinksOptions } from "./external-links";
4+
import { externalLinkArrow } from "./external-links";
55
import type { Root } from "hast";
66
import type { MdxTextExpression } from "mdast-util-mdx-expression";
77

@@ -34,7 +34,7 @@ export default function () {
3434
} else {
3535
if (!element.properties.id) {
3636
const string = toString(element)
37-
.replaceAll(rehypeExternalLinksOptions.content.value, "")
37+
.replaceAll(externalLinkArrow, "")
3838
.trimEnd();
3939

4040
element.properties.id = slugs.slug(string);

src/plugins/rehype/index.node.test.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ describe("heading-slugs", () => {
1515
.data("settings", {
1616
fragment: true,
1717
})
18-
.use([rehypeParse, rehypeHeadingSlugs, rehypeStringify])
18+
.use([
19+
rehypeParse,
20+
rehypeExternalLinks,
21+
rehypeHeadingSlugs,
22+
rehypeStringify,
23+
])
1924
.process(html);
2025

2126
return file.toString();
@@ -32,6 +37,16 @@ describe("heading-slugs", () => {
3237

3338
expect(text).toMatchInlineSnapshot(`"<h2 id="bar">foo</h2>"`);
3439
});
40+
41+
test("does not add arrow if image children", async () => {
42+
const text = await process(
43+
'<h2 id="bar"><a href="https://example.com">foo</a></h2>',
44+
);
45+
46+
expect(text).toMatchInlineSnapshot(
47+
`"<h2 id="bar"><a href="https://example.com" target="_blank" rel="noopener">foo<span class="external-link"> ↗</span></a></h2>"`,
48+
);
49+
});
3550
});
3651

3752
describe("external-links", () => {
@@ -59,6 +74,16 @@ describe("external-links", () => {
5974

6075
expect(text).toMatchInlineSnapshot(`"<a href="/">foo</a>"`);
6176
});
77+
78+
test("does not add arrow if image children", async () => {
79+
const text = await process(
80+
'<a href="https://example.com"><img src="/image.jpg" /></a>',
81+
);
82+
83+
expect(text).toMatchInlineSnapshot(
84+
`"<a href="https://example.com" target="_blank" rel="noopener"><img src="/image.jpg"></a>"`,
85+
);
86+
});
6287
});
6388

6489
describe("autolink-headings", () => {

src/util/props.node.test.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, expect, test } from "vitest";
22
import { generateDescription } from "./props";
3-
import { rehypeExternalLinksOptions } from "~/plugins/rehype/external-links";
3+
import { externalLinkArrow } from "~/plugins/rehype/external-links";
44

55
describe("description", () => {
66
describe("markdown", () => {
@@ -13,10 +13,8 @@ describe("description", () => {
1313
});
1414

1515
test("removes external link icon", async () => {
16-
const icon = rehypeExternalLinksOptions.content.value;
17-
1816
const desc = await generateDescription({
19-
markdown: `[links${icon}](/) and **${icon}stuff**`,
17+
markdown: `[links${externalLinkArrow}](/) and **${externalLinkArrow}stuff**`,
2018
});
2119

2220
expect(desc).toEqual("links and \\*\\*stuff\\*\\*");

src/util/props.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { parse } from "node-html-parser";
33
import he from "he";
44
import { remark } from "remark";
55
import strip from "strip-markdown";
6-
import { rehypeExternalLinksOptions } from "~/plugins/rehype/external-links";
6+
import { externalLinkArrow } from "~/plugins/rehype/external-links";
77

88
type TableOfContentsItems = NonNullable<StarlightRouteData["toc"]>["items"];
99

@@ -84,7 +84,5 @@ export async function generateDescription({
8484
if (paragraph) description = he.decode(paragraph.innerText);
8585
}
8686

87-
return description
88-
?.replaceAll(rehypeExternalLinksOptions.content.value, "")
89-
.trim();
87+
return description?.replaceAll(externalLinkArrow, "").trim();
9088
}

src/util/sidebar.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { AstroGlobal } from "astro";
22
import type { StarlightRouteData } from "@astrojs/starlight/route-data";
33

44
import { getEntry, getCollection } from "astro:content";
5-
import { rehypeExternalLinksOptions } from "~/plugins/rehype/external-links";
5+
import { externalLinkArrow } from "~/plugins/rehype/external-links";
66

77
type Link = Extract<StarlightRouteData["sidebar"][0], { type: "link" }> & {
88
order?: number;
@@ -280,7 +280,7 @@ async function handleLink(link: Link): Promise<Link> {
280280
if (frontmatter.external_link && !frontmatter.sidebar.group?.hideIndex) {
281281
return {
282282
...link,
283-
label: link.label.concat(rehypeExternalLinksOptions.content.value),
283+
label: link.label.concat(externalLinkArrow),
284284
href: frontmatter.external_link,
285285
badge: frontmatter.external_link.startsWith("/api")
286286
? {

0 commit comments

Comments
 (0)