Skip to content

Commit baf2a21

Browse files
committed
Improve expandable content copy logic with better code block detection
1 parent 9fc328a commit baf2a21

File tree

1 file changed

+29
-17
lines changed

1 file changed

+29
-17
lines changed

src/components/expandable/index.tsx

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
'use client';
22

3-
import {ReactNode, useCallback, useEffect, useRef, useState} from 'react';
4-
import {ChevronDownIcon, ChevronRightIcon} from '@radix-ui/react-icons';
3+
import { ReactNode, useCallback, useEffect, useRef, useState } from 'react';
4+
import { ChevronDownIcon, ChevronRightIcon } from '@radix-ui/react-icons';
55
import * as Sentry from '@sentry/nextjs';
66

7-
import {usePlausibleEvent} from 'sentry-docs/hooks/usePlausibleEvent';
7+
import { usePlausibleEvent } from 'sentry-docs/hooks/usePlausibleEvent';
88

99
// explicitly not usig CSS modules here
1010
// because there's some prerendered content that depends on these exact class names
@@ -41,12 +41,12 @@ export function Expandable({
4141
const [isExpanded, setIsExpanded] = useState(false);
4242
const [copied, setCopied] = useState(false);
4343
const contentRef = useRef<HTMLDivElement>(null);
44-
const {emit} = usePlausibleEvent();
44+
const { emit } = usePlausibleEvent();
4545

4646
// Ensure we scroll to the element if the URL hash matches
4747
useEffect(() => {
4848
if (!id) {
49-
return () => {};
49+
return () => { };
5050
}
5151

5252
if (window.location.hash === `#${id}`) {
@@ -78,24 +78,36 @@ export function Expandable({
7878
return;
7979
}
8080

81-
emit('Copy Expandable Content', {props: {page: window.location.pathname, title}});
81+
emit('Copy Expandable Content', { props: { page: window.location.pathname, title } });
8282

83-
// Attempt to get text from markdown code blocks if they exist
84-
const codeBlocks = contentRef.current.querySelectorAll('code');
83+
// First, try to get text from main code blocks (those inside pre elements)
84+
const preCodeBlocks = contentRef.current.querySelectorAll('pre code');
8585
let contentToCopy = '';
8686

87-
if (codeBlocks.length > 0) {
88-
// If there are code blocks, concatenate their text content
89-
codeBlocks.forEach(block => {
90-
// Exclude code elements within other code elements (e.g. inline code in a block)
91-
if (!block.closest('code')?.parentElement?.closest('code')) {
92-
contentToCopy += (block.textContent || '') + '\n';
93-
}
87+
if (preCodeBlocks.length > 0) {
88+
// If there are pre code blocks, concatenate their text content
89+
preCodeBlocks.forEach(block => {
90+
contentToCopy += (block.textContent || '') + '\n';
9491
});
9592
contentToCopy = contentToCopy.trim();
93+
} else {
94+
// Fallback: Look for large standalone code blocks (not inline code)
95+
const allCodeBlocks = contentRef.current.querySelectorAll('code');
96+
const largeCodeBlocks = Array.from(allCodeBlocks).filter((block: Element) => {
97+
// Skip inline code (usually short and inside paragraphs)
98+
const isInlineCode = block.closest('p') !== null && (block.textContent?.length || 0) < 100;
99+
return !isInlineCode;
100+
});
101+
102+
if (largeCodeBlocks.length > 0) {
103+
largeCodeBlocks.forEach((block: Element) => {
104+
contentToCopy += (block.textContent || '') + '\n';
105+
});
106+
contentToCopy = contentToCopy.trim();
107+
}
96108
}
97109

98-
// Fallback to the whole content if no code blocks or if they are empty
110+
// Final fallback to the whole content if no code blocks or if they are empty
99111
if (!contentToCopy && contentRef.current.textContent) {
100112
contentToCopy = contentRef.current.textContent.trim();
101113
}
@@ -123,7 +135,7 @@ export function Expandable({
123135
setIsExpanded(newVal);
124136

125137
if (newVal) {
126-
emit('Open Expandable', {props: {page: window.location.pathname, title}});
138+
emit('Open Expandable', { props: { page: window.location.pathname, title } });
127139
}
128140

129141
if (id) {

0 commit comments

Comments
 (0)