Skip to content

Commit 28075ad

Browse files
committed
update blog
1 parent 61ef05b commit 28075ad

3 files changed

Lines changed: 102 additions & 1 deletion

File tree

48.9 KB
Binary file not shown.

src/content/pages/about.mdx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,24 @@ At a high level, I help organizations connect their products with developers by
4242

4343
I strongly believe in learning by doing. I experiment, build, and share real experiences — including the lessons learned along the way.
4444

45-
## Journey, Growth & Milestones
45+
<div class="not-prose my-6 flex items-center justify-between gap-4">
46+
<h2 id="journey-growth-milestones" class="m-0 flex-1 text-left text-2xl font-semibold tracking-tight text-zinc-900 dark:text-zinc-100">
47+
Journey, Growth &amp; Milestones
48+
</h2>
49+
<a
50+
href="https://ivikramsahu.github.io/vikramsahu-blog/Vikram%20Sahu%20-%20PM%20%26%20DevRel.pdf"
51+
download="Vikram-Sahu-Resume.pdf"
52+
class="inline-flex shrink-0 items-center gap-2 rounded-lg border border-zinc-200 bg-white px-3 py-2 text-sm font-medium text-zinc-800 no-underline shadow-sm hover:bg-zinc-50 focus:outline-none focus:ring-2 focus:ring-zinc-300 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-100 dark:hover:bg-zinc-900 dark:focus:ring-zinc-700"
53+
>
54+
<svg aria-hidden="true" viewBox="0 0 24 24" class="h-4 w-4 text-red-600">
55+
<path
56+
fill="currentColor"
57+
d="M6 2h8l4 4v16a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2Zm8 1.5V7h3.5L14 3.5ZM8 11h8v2H8v-2Zm0 4h8v2H8v-2Zm0 4h6v2H8v-2Z"
58+
/>
59+
</svg>
60+
<span>Download Resume</span>
61+
</a>
62+
</div>
4663

4764
<JourneyRoadmap />
4865

src/pages/about.astro

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,88 @@ import AboutContent from '../content/pages/about.mdx';
77
<div class="openai-prose mx-auto w-full max-w-[46rem] min-w-0">
88
<AboutContent />
99
</div>
10+
11+
<script>
12+
(() => {
13+
const container = document.querySelector('.openai-prose');
14+
if (!container) return;
15+
16+
const headings = Array.from(container.querySelectorAll('h1, h2, h3, h4, h5, h6'));
17+
if (headings.length === 0) return;
18+
19+
const used = new Set();
20+
for (const h of headings) {
21+
if (h.id) used.add(h.id);
22+
}
23+
24+
const slugify = (s) => {
25+
return String(s || '')
26+
.toLowerCase()
27+
.trim()
28+
.replace(/['’]/g, '')
29+
.replace(/[^a-z0-9]+/g, '-')
30+
.replace(/^-+|-+$/g, '');
31+
};
32+
33+
const ensureId = (h) => {
34+
if (h.id) return h.id;
35+
const base = slugify(h.textContent);
36+
let id = base || 'section';
37+
let n = 2;
38+
while (used.has(id)) {
39+
id = `${base || 'section'}-${n}`;
40+
n += 1;
41+
}
42+
h.id = id;
43+
used.add(id);
44+
return id;
45+
};
46+
47+
const copyText = async (text) => {
48+
if (navigator.clipboard && window.isSecureContext) {
49+
await navigator.clipboard.writeText(text);
50+
return;
51+
}
52+
const ta = document.createElement('textarea');
53+
ta.value = text;
54+
ta.setAttribute('readonly', '');
55+
ta.style.position = 'fixed';
56+
ta.style.top = '-9999px';
57+
document.body.appendChild(ta);
58+
ta.select();
59+
document.execCommand('copy');
60+
document.body.removeChild(ta);
61+
};
62+
63+
const copyHeadingLink = async (h) => {
64+
const id = ensureId(h);
65+
const u = new URL(window.location.href);
66+
u.hash = id;
67+
await copyText(u.toString());
68+
window.history.replaceState(null, '', u.toString());
69+
70+
const prevTitle = h.getAttribute('title') || '';
71+
h.setAttribute('title', 'Copied link');
72+
window.setTimeout(() => {
73+
if (prevTitle) h.setAttribute('title', prevTitle);
74+
else h.removeAttribute('title');
75+
}, 1200);
76+
};
77+
78+
for (const h of headings) {
79+
ensureId(h);
80+
h.classList.add('cursor-pointer', 'select-none');
81+
h.setAttribute('role', 'button');
82+
h.tabIndex = 0;
83+
h.addEventListener('click', () => {
84+
copyHeadingLink(h).catch(() => {});
85+
});
86+
h.addEventListener('keydown', (e) => {
87+
if (e.key !== 'Enter' && e.key !== ' ') return;
88+
e.preventDefault();
89+
copyHeadingLink(h).catch(() => {});
90+
});
91+
}
92+
})();
93+
</script>
1094
</BaseLayout>

0 commit comments

Comments
 (0)