PageSourceSearch

https://pkl-lang.org/_/js/site-support.js

js pkl-lang.org collected 2026-09-24 18:03:32 UTC 4,304 bytes, 159 lines download raw bytes

1// ===----------------------------------------------------------------------===//
2// Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//	https://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15// ===----------------------------------------------------------------------===//
16(function () {
17  // Opens <details> blocks if anchor tags target elements inside them.
18  const openTarget = () => {
19    const hash = window.location.hash;
20    if (hash.length === 0) {
21      return;
22    }
23    const target = document.querySelector(hash);
24    if (!target) {
25      return;
26    }
27    const details = target.closest("details");
28    if (!details) {
29      return;
30    }
31    details.open = true;
32  }
33  window.addEventListener("hashchange", openTarget);
34  openTarget();
35
36  window.addEventListener("load", function () {
37    const tablists = document.querySelectorAll('[role=tablist].automatic');
38    for (let i = 0; i < tablists.length; i++) {
39      new Tabs(tablists[i], i === 0);
40    }
41  });
42})();
43
44class Tabs {
45  constructor(node, autoScroll) {
46    this.tabs = [];
47    this.firstTab = null;
48    this.lastTab = null;
49    this.tabSelected = false;
50    this.tabIndex = 0;
51
52    this.tabs = Array.from(node.querySelectorAll('[role=tab]'));
53    this.tabpanels = [];
54
55    for (let i = 0; i < this.tabs.length; i += 1) {
56      const tab = this.tabs[i];
57      const tabpanel = document.getElementById(tab.getAttribute('aria-controls'));
58
59      tab.tabIndex = -1;
60      tab.setAttribute('aria-selected', 'false');
61      this.tabpanels.push(tabpanel);
62
63      tab.addEventListener('keydown', this.onKeydown.bind(this));
64      tab.addEventListener('click', this.onClick.bind(this));
65
66      if (!this.firstTab) {
67        this.firstTab = tab;
68      }
69      this.lastTab = tab;
70    }
71
72    this.setSelectedTab(this.firstTab, false);
73  }
74
75  setSelectedTab(currentTab, setFocus = true) {
76    for (let i = 0; i < this.tabs.length; i += 1) {
77      const tab = this.tabs[i];
78      if (currentTab === tab) {
79        tab.setAttribute('aria-selected', 'true');
80        tab.removeAttribute('tabindex');
81        this.tabpanels[i].classList.remove('is-hidden');
82        if (setFocus) {
83          tab.focus();
84        }
85      } else {
86        tab.setAttribute('aria-selected', 'false');
87        tab.tabIndex = -1;
88        this.tabpanels[i].classList.add('is-hidden');
89      }
90    }
91  }
92
93  setSelectedToPreviousTab(currentTab) {
94    let index;
95    if (currentTab === this.firstTab) {
96      this.setSelectedTab(this.lastTab);
97    } else {
98      index = this.tabs.indexOf(currentTab);
99      this.setSelectedTab(this.tabs[index - 1]);
100    }
101  }
102
103  setSelectedToNextTab(currentTab, setFocus = true) {
104    let index;
105    if (currentTab === this.lastTab) {
106      this.setSelectedTab(this.firstTab, setFocus);
107    } else {
108      index = this.tabs.indexOf(currentTab);
109      this.setSelectedTab(this.tabs[index + 1], setFocus);
110    }
111  }
112
113  /* EVENT HANDLERS */
114
115  onKeydown(event) {
116    const tgt = event.currentTarget;
117    let flag = false;
118
119    switch (event.key) {
120      case 'ArrowLeft':
121        this.setSelectedToPreviousTab(tgt);
122        this.tabSelected = true;
123        flag = true;
124        break;
125
126      case 'ArrowRight':
127        this.setSelectedToNextTab(tgt);
128        this.tabSelected = true;
129        flag = true;
130        break;
131
132      case 'Home':
133        this.setSelectedTab(this.firstTab);
134        this.tabSelected = true;
135        flag = true;
136        break;
137
138      case 'End':
139        this.setSelectedTab(this.lastTab);
140        this.tabSelected = true;
141        flag = true;
142        break;
143
144      default:
145        break;
146    }
147
148    if (flag) {
149      event.stopPropagation();
150      event.preventDefault();
151    }
152  }
153
154  onClick(event) {
155    this.setSelectedTab(event.currentTarget);
156    this.tabSelected = true;
157  }
158
159}

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.