PageSourceSearch

https://aymuos15.github.io/js/utils.js

js aymuos15.github.io collected 2026-10-03 08:40:50 UTC 3,585 bytes, 144 lines download raw bytes

1// Pastel rainbow link colors
2const pastelColors = [
3  "#e8a0bf",
4  "#f0b8a8",
5  "#f2cc8f",
6  "#b5d99c",
7  "#a8d8ea",
8  "#b8b8f0",
9  "#d4a5e5",
10  "#f5a8a8",
11  "#a8e0c8",
12  "#c4b8e8",
13  "#e8c8a0",
14  "#a0c8e8",
15];
16
17// Shared with typer.js (separate script scope) for per-glyph pastel colors.
18window.pastelColors = pastelColors;
19
20const LETTER = /[A-Za-z]/;
21
22function colorizeLinks() {
23  for (const link of document.querySelectorAll("main a")) {
24    const color = pastelColors[Math.floor(Math.random() * pastelColors.length)];
25    link.style.color = color;
26  }
27}
28
29function colorizeRandomLetters(el, accentRatio = 0.28) {
30  const text = el.dataset.original || el.textContent;
31  const letterPositions = [];
32
33  el.dataset.original = text;
34  for (const [index, ch] of [...text].entries()) {
35    if (LETTER.test(ch)) {
36      letterPositions.push(index);
37    }
38  }
39
40  if (!letterPositions.length) {
41    return;
42  }
43
44  const accentCount = Math.max(
45    1,
46    Math.floor(letterPositions.length * accentRatio)
47  );
48  const accentPositions = new Set();
49
50  while (accentPositions.size < Math.min(accentCount, letterPositions.length)) {
51    const randomIndex = Math.floor(Math.random() * letterPositions.length);
52    accentPositions.add(letterPositions[randomIndex]);
53  }
54
55  const fragment = document.createDocumentFragment();
56  for (const [index, ch] of [...text].entries()) {
57    if (!LETTER.test(ch)) {
58      fragment.appendChild(document.createTextNode(ch));
59      return;
60    }
61
62    const span = document.createElement("span");
63    span.textContent = ch;
64
65    if (accentPositions.has(index)) {
66      span.style.color =
67        pastelColors[Math.floor(Math.random() * pastelColors.length)];
68    }
69
70    fragment.appendChild(span);
71  }
72
73  el.replaceChildren(fragment);
74}
75
76// Social icon highlights per section
77const socialHighlights = {
78  about: { linkedin: "#0A66C2", x: null },
79  microblog: { scholar: "#4285F4" },
80  news: { github: null, pytorch: "#EE4C2C" },
81  research: { scholar: "#4285F4" },
82};
83
84// GitHub & X brand is black/white — just use site text color
85Object.defineProperty(socialHighlights.news, "github", {
86  get() {
87    return window
88      .getComputedStyle(document.documentElement)
89      .getPropertyValue("--text")
90      .trim();
91  },
92});
93Object.defineProperty(socialHighlights.about, "x", {
94  get() {
95    return window
96      .getComputedStyle(document.documentElement)
97      .getPropertyValue("--text")
98      .trim();
99  },
100});
101
102function highlightSocials(sectionId) {
103  const map = socialHighlights[sectionId];
104  for (const a of document.querySelectorAll(".social-links a[data-social]")) {
105    a.style.color = map?.[a.dataset.social] || "";
106  }
107}
108
109// Rainbow footer text
110const footerCity = document.getElementById("footer-city");
111const footerEmail = document.getElementById("footer-email");
112
113function rainbowText(el) {
114  const text = el.dataset.original || el.textContent;
115  el.dataset.original = text;
116  el.innerHTML = [...text]
117    .map((ch, i) =>
118      ch === " "
119        ? " "
120        : `<span class="rainbow-ch" style="color:${pastelColors[i % pastelColors.length]};animation-delay:${i * 30}ms">${ch}</span>`
121    )
122    .join("");
123}
124
125function resetText(el) {
126  if (el.dataset.original) {
127    el.innerHTML = [...el.dataset.original]
128      .map((ch) => (ch === " " ? " " : `<span>${ch}</span>`))
129      .join("");
130  }
131}
132
133function updateFooterRainbow(sectionId) {
134  if (sectionId === "gallery") {
135    rainbowText(footerCity);
136  } else {
137    resetText(footerCity);
138  }
139  if (sectionId === "research") {
140    rainbowText(footerEmail);
141  } else {
142    resetText(footerEmail);
143  }
144}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.