-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
404 lines (341 loc) · 12.1 KB
/
script.js
File metadata and controls
404 lines (341 loc) · 12.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
/**
* Handles the favicon based on the visibility of the page.
*/
const faviconHandler = () => {
const favicon = document.querySelector(
'link[rel="icon"][type="image/x-icon"]'
);
if (!favicon) {
console.warn("Favicon link element not found.");
return;
}
// get current favicon path
const currentFavicon = favicon.getAttribute("href");
// Set the favicon path based on visibility
// if the page is hidden, set a different favicon i.e. add a "hidden" suffix
const faviconPath = document.hidden
? currentFavicon.replace(/(\.[a-z]{2,4})$/, "-inactive$1")
: currentFavicon.replace(/-inactive(\.[a-z]{2,4})$/, "$1");
favicon.setAttribute("href", faviconPath);
};
/**
* Optimizes smooth scroll handling.
* @param {Element} element - The element to scroll to.
*/
const smoothScrollTo = (element) => {
if (!element) {
console.warn("Attempted to scroll to a null element.");
return;
}
// Use native smooth scroll with fallback
if ("scrollBehavior" in document.documentElement.style) {
element.scrollIntoView({
behavior: "smooth",
block: "start",
});
} else {
// Fallback for browsers that don't support smooth scroll
window.scrollTo({
top: element.offsetTop,
behavior: "smooth",
});
}
};
/**
* Handles changes to the URL hash to scroll to the target element.
* @returns {void}
*/
const hashChangerHandler = () => {
const hash = window.location.hash;
if (!hash) {
return;
}
// Escape potential special characters in the hash for robust selection
const escapedHash = CSS.escape(hash);
const element = document.querySelector(`[href="${escapedHash}"]`);
if (!element) {
console.warn(`Element with href="${escapedHash}" not found.`);
return;
}
smoothScrollTo(element);
};
/**
* Updates the active section based on the current scroll position using debouncing.
*/
const updateActiveSection = (() => {
// Cache selectors outside the function to avoid repeated lookups
const activators = document.querySelectorAll(".c-heading-anchor");
const headingLinks = document.querySelectorAll(".c-heading-anchor__link");
let scrollTimeout;
const debounceDelay = 100;
const processScroll = () => {
requestAnimationFrame(() => {
if (window.scrollY <= 50 && window.location.hash) {
headingLinks.forEach((link) =>
link.classList.remove("c-heading-anchor__link--active")
);
history.replaceState(null, null, window.location.pathname);
return;
}
let currentActivator = null;
let maxVisibility = 0;
for (let i = 0; i < activators.length; i++) {
const activator = activators[i];
const rect = activator.getBoundingClientRect();
if (rect.top < window.innerHeight && rect.bottom > 0) {
const visibility =
Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0);
if (visibility > maxVisibility) {
maxVisibility = visibility;
currentActivator = activator.querySelector(
"a[class='c-heading-anchor__link']"
);
}
}
}
if (currentActivator) {
const currentHref = currentActivator.getAttribute("href");
const currentHash = window.location.hash;
if (currentHash !== currentHref) {
history.replaceState(null, null, currentHref);
headingLinks.forEach((link) => {
link.classList.toggle(
"c-heading-anchor__link--active",
link.getAttribute("href") === currentHref
);
});
}
} else {
headingLinks.forEach((link) =>
link.classList.remove("c-heading-anchor__link--active")
);
if (window.location.hash) {
history.replaceState(null, null, window.location.pathname);
}
}
});
};
return () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(processScroll, debounceDelay);
};
})();
/**
* Main function to handle all event listeners.
*/
const scrollManager = () => {
window.addEventListener("hashchange", hashChangerHandler);
// Handle initial hash on page load
if (window.location.hash) {
requestAnimationFrame(() => {
const escapedHash = CSS.escape(window.location.hash);
const targetElement = document.querySelector(`[href="${escapedHash}"]`);
if (targetElement) {
requestAnimationFrame(() => smoothScrollTo(targetElement));
}
});
}
window.addEventListener("scroll", updateActiveSection, {
passive: true,
});
};
/**
* TLDR Generator functionality
*/
const tldrGenerator = (() => {
let modal, openBtn, closeBtn, categoryButtons;
// Prompt templates for each category - optimized for real-world use cases
const prompts = {
professional: `Visit ${window.location.origin} and analyze the website content. Also check https://github.com/ragarwalll if mentioned.
Create a professional TLDR summary that would be useful for:
- Recruiters scanning LinkedIn profiles
- Hiring managers reviewing candidates
- Potential collaborators or clients
- Networking events and introductions
REQUIREMENTS:
1. Extract key information:
- Current role and company
- Years of experience and career progression
- Core technical skills (be specific: languages, frameworks, tools)
- Notable projects with impact/metrics (downloads, users, etc.)
- Problem-solving approach and work philosophy
- Educational background
2. Format as a concise professional bio (2-3 short paragraphs):
- First paragraph: Current role, experience level, and primary expertise
- Second paragraph: Key achievements, projects, and technical strengths
- Third paragraph (optional): Approach to work, values, or unique differentiators
3. Style guidelines:
- Professional but approachable tone
- Use specific technologies and metrics when available
- Focus on outcomes and impact, not just responsibilities
- Avoid buzzwords and generic statements
- Be authentic to the website's tone
- No emojis
4. Make it scannable and LinkedIn-ready - something that can be copied directly into a professional profile or email introduction.`,
friendly: `Visit ${window.location.origin} and read through the website to understand Rahul's personality and interests.
Create a friendly, casual TLDR that would be useful for:
- Introducing him to new friends or social groups
- Social media bios (Twitter, Instagram, etc.)
- Casual networking or meetups
- When someone asks "tell me about yourself" in a non-professional setting
REQUIREMENTS:
1. Extract key information:
- Personal background and story
- Hobbies, interests, and passions
- Personality traits and quirks
- Creative pursuits and adventures
- What makes him interesting as a person
- Projects mentioned casually (not too technical)
2. Format as a friendly introduction (2-3 paragraphs):
- First paragraph: Who he is and what he's passionate about
- Second paragraph: Interests, hobbies, and personality highlights
- Third paragraph: Fun facts or what makes him unique
3. Style guidelines:
- Warm, conversational, and approachable
- Light humor is welcome
- Focus on personality over professional achievements
- Use casual language but stay authentic
- Can include emojis sparingly if it fits the tone
- Make it relatable and human
4. Make it something a friend would say when introducing him - natural, engaging, and easy to remember.`,
dating: `Visit ${window.location.origin} and analyze the website to understand Rahul's personality, interests, and what makes him interesting.
Create an engaging dating profile TLDR that would be useful for:
- Dating apps (Hinge, Bumble, Tinder bios)
- Social introductions in dating contexts
- Personal connection and attraction
REQUIREMENTS:
1. Extract key information:
- Age and location (if mentioned)
- Unique hobbies and interests
- Personality traits and energy
- Creative pursuits and adventures
- What makes him stand out
- Balance of professional and personal life
- Values and what matters to him
2. Format as an attractive dating profile (2-3 short paragraphs):
- First paragraph: Engaging hook that shows personality and confidence
- Second paragraph: Interests, passions, and what he enjoys doing
- Third paragraph: What makes him interesting or what he's looking for (if appropriate)
3. Style guidelines:
- Confident but not arrogant
- Authentic and genuine
- Playful and charming
- Show personality, not just list facts
- Avoid clichés ("I love travel and food")
- Be specific about interests
- Light humor and wit are welcome
- Emotionally intelligent tone
4. Make it appealing and authentic - something that would make someone want to know more about him. Focus on what makes him interesting as a person, not just his job.`,
};
const openModal = () => {
console.log("Opening modal", modal);
if (modal) {
modal.setAttribute("aria-hidden", "false");
modal.classList.remove("c-tldr-modal__hidden");
document.body.style.overflow = "hidden";
} else {
console.error("Modal not found when trying to open");
}
};
const closeModal = () => {
if (modal) {
modal.setAttribute("aria-hidden", "true");
modal.classList.add("c-tldr-modal__hidden");
document.body.style.overflow = "";
removeTLDRQueryParam();
}
};
const generateTLDR = (category) => {
const prompt = prompts[category];
if (!prompt) {
console.error("Invalid category:", category);
return;
}
// Try URL parameter method first
const encodedPrompt = encodeURIComponent(prompt);
const chatgptUrl = `https://chat.openai.com/?q=${encodedPrompt}`;
// Open ChatGPT with URL parameter
window.open(chatgptUrl, "_blank");
closeModal();
};
const init = () => {
// Query DOM elements when initializing
modal = document.getElementById("tldr-modal");
openBtn = document.getElementById("tldr-generator-btn");
closeBtn = modal?.querySelector(".c-tldr-modal__close");
categoryButtons = modal?.querySelectorAll(".c-tldr-category");
if (!modal || !openBtn) {
console.error("TLDR Generator: Modal or button not found", {
modal,
openBtn,
});
return;
}
console.log("TLDR Generator initialized", {
modal,
openBtn,
categoryButtons: categoryButtons?.length,
});
// Open modal
openBtn.addEventListener("click", (e) => {
setTLDRQueryParam();
openModal();
});
// Close modal
closeBtn?.addEventListener("click", closeModal);
// Close on overlay click
const overlay = modal.querySelector(".c-tldr-modal__overlay");
overlay?.addEventListener("click", closeModal);
// Close on Escape key
document.addEventListener("keydown", (e) => {
if (e.key === "Escape" && modal.getAttribute("aria-hidden") === "false") {
closeModal();
}
});
// Handle category selection
categoryButtons?.forEach((btn) => {
btn.addEventListener("click", () => {
const category = btn.getAttribute("data-category");
generateTLDR(category);
});
});
};
return { init, openModal };
})();
/**
* Checks if the URL contains ?show-tldr
* @returns {boolean}
*/
const shouldShowTLDR = () => {
const params = new URLSearchParams(window.location.search);
return params.has("show-tldr");
};
const setTLDRQueryParam = () => {
const url = new URL(window.location.href);
url.searchParams.set("show-tldr", "true");
history.pushState(null, "", url.toString());
};
const removeTLDRQueryParam = () => {
const url = new URL(window.location.href);
url.searchParams.delete("show-tldr");
history.replaceState(null, "", url.toString());
};
const onReady = () => {
faviconHandler();
scrollManager();
tldrGenerator.init();
if (shouldShowTLDR()) {
requestAnimationFrame(() => {
tldrGenerator.openModal();
// Clean URL without reload
const url = new URL(window.location.href);
url.searchParams.delete("show-tldr");
history.replaceState(null, "", url.toString());
});
}
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", onReady);
} else {
onReady();
}