Skip to content

Commit 576cae2

Browse files
committed
Add copy article functionality to DeepSeek Sparse Attention page
- Introduced a button to copy the article's markdown content to the clipboard, enhancing user experience. - Implemented state management for copy success feedback, providing visual confirmation to users. - Updated the layout to include the new button while maintaining overall design consistency.
1 parent a442cba commit 576cae2

2 files changed

Lines changed: 87 additions & 56 deletions

File tree

app/blog/deepseek-sparse-attention/page.tsx

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export default function DeepSeekProject() {
1616
const [markdownContent, setMarkdownContent] = useState<string>('');
1717
const [heroData, setHeroData] = useState<HeroData | null>(null);
1818
const [isLoading, setIsLoading] = useState(true);
19+
const [copySuccess, setCopySuccess] = useState(false);
1920

2021
useEffect(() => {
2122
const fetchMarkdownContent = async () => {
@@ -98,6 +99,24 @@ export default function DeepSeekProject() {
9899
fetchMarkdownContent();
99100
}, [language]);
100101

102+
const handleCopyArticle = async () => {
103+
try {
104+
// Get the raw markdown content without frontmatter
105+
const filename = language === 'zh' ? 'deepseek-sparse-attention-content-zh.md' : 'deepseek-sparse-attention-content.md';
106+
const response = await fetch(`/content/deepseek-sparse-attention/${filename}`);
107+
const content = await response.text();
108+
109+
// Remove frontmatter if present
110+
const contentWithoutFrontmatter = content.replace(/^---\n[\s\S]*?\n---\n/, '');
111+
112+
await navigator.clipboard.writeText(contentWithoutFrontmatter);
113+
setCopySuccess(true);
114+
setTimeout(() => setCopySuccess(false), 2000);
115+
} catch (error) {
116+
console.error('Failed to copy article:', error);
117+
}
118+
};
119+
101120
if (isLoading) {
102121
return (
103122
<div className="min-h-screen bg-gradient-to-br from-slate-950 via-slate-900 to-slate-950 flex items-center justify-center">
@@ -184,8 +203,36 @@ export default function DeepSeekProject() {
184203
<article className="max-w-4xl mx-auto">
185204
{/* Content Card */}
186205
<div className="bg-white/5 backdrop-blur-xl border border-white/10 rounded-3xl shadow-2xl overflow-hidden">
206+
{/* Copy Article Button */}
207+
<div className="px-8 sm:px-12 pt-8 pb-4">
208+
<button
209+
onClick={handleCopyArticle}
210+
className={`group flex items-center gap-2 px-4 py-2 rounded-lg font-medium transition-all duration-300 ${
211+
copySuccess
212+
? 'bg-green-500/20 text-green-400 border border-green-500/30'
213+
: 'bg-white/5 hover:bg-white/10 text-slate-300 hover:text-blue-400 border border-white/10 hover:border-blue-500/50'
214+
}`}
215+
>
216+
{copySuccess ? (
217+
<>
218+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
219+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
220+
</svg>
221+
{language === 'en' ? 'Copied!' : '已复制!'}
222+
</>
223+
) : (
224+
<>
225+
<svg className="w-4 h-4 group-hover:scale-110 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
226+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
227+
</svg>
228+
{language === 'en' ? 'Copy Article' : '复制文章'}
229+
</>
230+
)}
231+
</button>
232+
</div>
233+
187234
{/* Article Body */}
188-
<div className="px-8 sm:px-12 py-12">
235+
<div className="px-8 sm:px-12 pb-12">
189236
<div className="prose prose-lg prose-invert max-w-none">
190237
<MarkdownRenderer content={markdownContent} />
191238
</div>

0 commit comments

Comments
 (0)