Skip to content

Commit 928ee4e

Browse files
committed
added copy short links to headings
1 parent 9473fbb commit 928ee4e

2 files changed

Lines changed: 70 additions & 13 deletions

File tree

src/components/markdown/Heading.astro

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,57 @@ const { node, headings } = Astro.props as Props;
1111
1212
const HeadingLevel = `h${node.depth}`
1313
const heading_line = node.position.start.line
14-
const slug = headings.find((entry)=>(entry.line == heading_line)).slug
14+
const entry = headings.find((entry)=>(entry.line == heading_line))
1515
---
16-
<HeadingLevel id={slug} class="heading bar">
17-
<a href={`#${slug}`} class="link">
18-
<div class="text">
19-
{node.children.map((node)=>(
20-
<Fragment set:html={toHtml(toHast(node))}></Fragment>
16+
<HeadingLevel id={entry.slug} class="heading bar">
17+
<div class="text">
18+
{node.children.map((node)=>(
19+
<Fragment set:html={toHtml(toHast(node))}></Fragment>
2120
))}
21+
</div>
22+
<div class="icon link">
23+
<a href={`#${entry.slug}`} class="link">
24+
<Svgicons filename="link"/>
25+
</a>
26+
<div class="icon copy" title="copy short link" data-sid={entry.sid}>
27+
<Svgicons filename="copy"/>
28+
</div>
2229
</div>
23-
<div class="icon"><Svgicons filename="link"/></div>
24-
</a>
2530
</HeadingLevel>
2631

2732
<style>
2833
.heading.bar{
2934
width: fit-content;
35+
display: flex;
36+
gap: 10px;
3037
}
31-
.link{
32-
display: flex;
33-
gap:10px;
38+
.icon{
39+
opacity: 0;
40+
}
41+
.heading.bar:hover .icon.link{
42+
opacity: 1;
43+
}
44+
.icon.link:hover .icon.copy{
45+
opacity: 1;
3446
}
35-
.link:hover{
36-
text-decoration: underline;
47+
.icon.copy{
48+
cursor: pointer;
49+
position: relative; /* Needed to position the 'Copied!' message correctly */
50+
}
51+
.link{
52+
display: flex;
53+
align-items: center;
54+
gap: 10px;
3755
}
3856
.icon :global(svg){
3957
width:16px;
58+
height:16px;
4059
fill:rgb(101, 96, 96);
4160
}
4261
.heading.bar :global(a){
4362
text-decoration: none;
4463
color: inherit;
4564
}
4665
</style>
66+
67+
<script src="./heading.js" />

src/components/markdown/heading.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
function init(){
3+
const copyIcons = document.querySelectorAll('.icon.copy');
4+
copyIcons.forEach(icon => {
5+
icon.addEventListener('click', function() {
6+
// Copy data-sid to clipboard
7+
const sid = this.getAttribute('data-sid');
8+
const url = `${window.location.origin}/${sid}`;
9+
navigator.clipboard.writeText(url).then(() => {
10+
// Show success message
11+
const message = document.createElement('span');
12+
message.textContent = 'Copied!';
13+
message.style.position = 'absolute';
14+
message.style.left = '100%';
15+
message.style.top = '0';
16+
//message.style.backgroundColor = 'white';
17+
message.style.color = 'white';
18+
//message.style.border = '1px solid black';
19+
message.style.padding = '2px 8px';
20+
message.style.fontSize = '0.75rem';
21+
message.style.marginLeft = '10px';
22+
this.appendChild(message);
23+
24+
// Remove the message after 1 second
25+
setTimeout(() => {
26+
this.removeChild(message);
27+
}, 1000);
28+
}).catch(err => {
29+
console.error('Failed to copy text: ', err);
30+
});
31+
});
32+
});
33+
}
34+
35+
document.addEventListener('DOMContentLoaded', init);
36+

0 commit comments

Comments
 (0)