PageSourceSearch

https://zaiye.art/home-preview.js?v=20260803-1

js zaiye.art collected 2026-10-02 01:15:51 UTC 2,583 bytes, 75 lines download raw bytes

1const stops = [...document.querySelectorAll(".studio-stop[data-scene]")];
2const sceneImage = document.querySelector(".scene-image");
3const zoneLinks = [...document.querySelectorAll(".zone-nav a")];
4const themeButton = document.querySelector("[data-theme-toggle]");
5let activeIndex = 0;
6
7function updateThemeButton() {
8  const dark = document.documentElement.dataset.theme === "dark";
9  themeButton.textContent = dark ? "☀" : "☾";
10  themeButton.setAttribute("aria-label", dark ? "切换到日间模式" : "切换到夜间模式");
11  themeButton.title = dark ? "日间模式" : "夜间模式";
12}
13
14themeButton.addEventListener("click", () => {
15  const nextTheme = document.documentElement.dataset.theme === "dark" ? "light" : "dark";
16  document.documentElement.dataset.theme = nextTheme;
17  localStorage.setItem("zaiye-site-theme", nextTheme);
18  updateThemeButton();
19});
20
21updateThemeButton();
22
23function revealScene() {
24  document.body.classList.add("scene-ready");
25}
26
27if (sceneImage.complete && sceneImage.naturalWidth) {
28  revealScene();
29} else {
30  sceneImage.addEventListener("load", revealScene, { once: true });
31  sceneImage.addEventListener("error", revealScene, { once: true });
32}
33
34function showStop(index) {
35  activeIndex = Math.max(0, Math.min(stops.length - 1, index));
36  const activeStop = stops[activeIndex];
37  document.body.dataset.scene = activeStop.dataset.scene;
38  stops.forEach((stop, stopIndex) => {
39    stop.classList.toggle("is-active", stopIndex === activeIndex);
40  });
41  zoneLinks.forEach((link) => {
42    const isCurrent = link.hash === `#${activeStop.id}`;
43    if (isCurrent) link.setAttribute("aria-current", "location");
44    else link.removeAttribute("aria-current");
45  });
46}
47
48function travelTo(index) {
49  const target = stops[Math.max(0, Math.min(stops.length - 1, index))];
50  target.scrollIntoView({ behavior: "smooth", block: "start" });
51}
52
53const observer = new IntersectionObserver((entries) => {
54  const visible = entries
55    .filter((entry) => entry.isIntersecting)
56    .sort((left, right) => right.intersectionRatio - left.intersectionRatio)[0];
57  if (!visible) return;
58  showStop(stops.indexOf(visible.target));
59}, { threshold: [0.45, 0.65, 0.85] });
60
61stops.forEach((stop) => observer.observe(stop));
62
63document.addEventListener("keydown", (event) => {
64  if (event.target.closest("a, button")) return;
65  if (["ArrowDown", "PageDown"].includes(event.key)) {
66    event.preventDefault();
67    travelTo(activeIndex + 1);
68  }
69  if (["ArrowUp", "PageUp"].includes(event.key)) {
70    event.preventDefault();
71    travelTo(activeIndex - 1);
72  }
73});
74
75showStop(0);

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.