-
Notifications
You must be signed in to change notification settings - Fork 6.1k
/
Copy pathinitialize.js
265 lines (229 loc) · 9.74 KB
/
initialize.js
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
const getLogoSrc = (isDark) => (isDark ? DARK_LOGO_PATH : LIGHT_LOGO_PATH);
const getModeIconSrc = (isDark) => (isDark ? SUN_ICON_PATH : MOON_ICON_PATH);
const getMenuIconSrc = (isDark) =>
isDark ? DARK_HAMBURGER_PATH : LIGHT_HAMBURGER_PATH;
function addFooterNote() {
const contentInfo = document.querySelector("div[role=contentinfo]");
const footerNote = document.createElement("p");
footerNote.classList.add("footer-note");
footerNote.innerHTML =
'Customized with ❤️ by the <a href="https://ethereum.org/" target="_blank">ethereum.org</a> team.';
contentInfo.parentNode.insertBefore(footerNote, contentInfo.nextSibling);
}
function rearrangeDom() {
const bodyDivs = document.querySelectorAll("body>div");
bodyDivs.forEach((div) => div.remove());
const wrapperDiv = document.createElement("div");
wrapperDiv.classList.add(WRAPPER_CLASS);
bodyDivs.forEach((div) => wrapperDiv.appendChild(div));
document.body.prepend(wrapperDiv);
const rstVersions = document.querySelector(".rst-versions");
const wyNavSide = document.querySelector("nav.wy-nav-side");
// NOTE: Since RTD migration to addons, `.rst-versions` is no longer present in the DOM.
// The following code is kept for compatibility with older versions.
// See: https://github.com/readthedocs/readthedocs.org/issues/11474
if (rstVersions && wyNavSide) {
rstVersions.remove();
wyNavSide.appendChild(rstVersions);
}
const backdrop = document.createElement("div");
backdrop.classList.add("backdrop");
wrapperDiv.appendChild(backdrop);
const content = document.querySelector(".wy-nav-content");
if (content) {
content.id = "content";
document.querySelector("section.wy-nav-content-wrap")?.remove();
document.querySelector(".wy-grid-for-nav")?.appendChild(content);
}
}
function buildHeader() {
const isDarkMode = localStorage.getItem(LS_COLOR_SCHEME) == DARK;
const header = document.createElement("div");
header.classList.add("unified-header");
document.querySelector(`.${WRAPPER_CLASS}`).prepend(header);
const innerHeader = document.createElement("div");
innerHeader.classList.add("inner-header");
header.appendChild(innerHeader);
const homeLink = document.createElement("a");
homeLink.classList.add("home-link");
homeLink.href = SOLIDITY_HOME_URL;
homeLink.ariaLabel = "Solidity home";
innerHeader.appendChild(homeLink);
const logo = document.createElement("img");
logo.classList.add(SOLIDITY_LOGO_CLASS);
logo.src = getLogoSrc(isDarkMode);
logo.alt = "Solidity logo";
homeLink.appendChild(logo);
const skipToContent = document.createElement("a");
skipToContent.classList.add("skip-to-content");
skipToContent.href = "#content";
skipToContent.innerText = "{skip to content}";
innerHeader.appendChild(skipToContent);
const navBar = document.createElement("nav");
navBar.classList.add("nav-bar");
innerHeader.appendChild(navBar);
const linkElements = NAV_LINKS.map(({ name, href }) => {
const link = document.createElement("a");
link.classList.add("nav-link");
link.setAttribute("key", name);
link.setAttribute("href", href);
link.setAttribute("aria-label", name);
if (href === FORUM_URL) {
link.classList.add("forum-link");
link.setAttribute("target", "_blank");
link.setAttribute("rel", "noopener noreferrer");
}
link.innerText = name;
return link;
});
linkElements.forEach((link) => navBar.appendChild(link));
// Flex wrapper for color mode and mobile menu buttons
const navButtonContainer = document.createElement("div");
navButtonContainer.classList.add("nav-button-container");
navBar.appendChild(navButtonContainer);
// Build color toggle
const toggleIcon = document.createElement("img");
toggleIcon.classList.add(COLOR_TOGGLE_ICON_CLASS);
toggleIcon.src = getModeIconSrc(isDarkMode);
toggleIcon.alt = "Color mode toggle icon";
toggleIcon.setAttribute("aria-hidden", "true");
toggleIcon.setAttribute("key", "toggle icon");
const colorModeButton = document.createElement("button");
colorModeButton.classList.add("color-toggle");
colorModeButton.setAttribute("type", "button");
colorModeButton.setAttribute("aria-label", "Toggle light dark mode");
colorModeButton.setAttribute("key", "color mode button");
colorModeButton.addEventListener("click", toggleColorMode);
colorModeButton.appendChild(toggleIcon);
navButtonContainer.appendChild(colorModeButton);
// Build mobile hamburger menu
const menuIcon = document.createElement("img");
menuIcon.classList.add(COLOR_TOGGLE_ICON_CLASS);
menuIcon.src = getMenuIconSrc(isDarkMode);
menuIcon.alt = "Toggle menu";
menuIcon.setAttribute("aria-hidden", "true");
menuIcon.setAttribute("key", "menu icon");
const menuButton = document.createElement("button");
menuButton.classList.add("color-toggle");
menuButton.classList.add("mobile-menu-button");
menuButton.setAttribute("type", "button");
menuButton.setAttribute("aria-label", "Toggle menu");
menuButton.setAttribute("key", "menu button");
menuButton.addEventListener("click", toggleMenu);
menuButton.appendChild(menuIcon);
navButtonContainer.appendChild(menuButton);
}
const updateActiveNavLink = () => {
const navLinks = document.querySelectorAll(".unified-header .nav-link");
navLinks.forEach((link) => {
const href = link.getAttribute("href");
if (document.documentURI.includes("contributing.html")) {
link.classList[href.includes("contributing.html") ? "add" : "remove"](
"active"
);
} else {
link.classList[document.documentURI.includes(href) ? "add" : "remove"](
"active"
);
}
});
};
document.addEventListener("locationchange", updateActiveNavLink);
function updateGitHubEditPath() {
// Replaces the version number in the GitHub edit path with "develop" if it exists.
// This is to ensure that the edit path always points to the `develop` branch instead of the specific version branch.
// Note that it will fail silently if the anchor element is not found, i.e. the page is not editable or
// if the sphinx_rtd_theme is updated to a version that changes the anchor element.
// See: https://github.com/readthedocs/sphinx_rtd_theme/blob/a1c2147b17cbf0e57b7d7a6450ad4d9a5ff362cf/sphinx_rtd_theme/breadcrumbs.html#L35
// TODO: We should consider a more robust way to handle this in the future.
const gitHubEditAnchor = document.querySelector(".wy-breadcrumbs-aside > a");
if (!gitHubEditAnchor) return;
const url = new URL(gitHubEditAnchor.href);
const split = url.pathname.split("/");
const versionIndex = split.indexOf("blob") + 1;
split[versionIndex] = "develop";
url.pathname = split.join("/");
gitHubEditAnchor.setAttribute("href", url.toString());
gitHubEditAnchor.setAttribute("target", "_blank");
gitHubEditAnchor.setAttribute("rel", "noopener noreferrer");
}
function initialize() {
// Rearrange DOM elements for styling
rearrangeDom();
// Check localStorage for existing color scheme preference
var prefersDark = localStorage.getItem(LS_COLOR_SCHEME) == DARK;
// Check link for search param "color"... it may be "light" or "dark"
var urlParams = new URLSearchParams(window.location.search);
if (urlParams.size > 0) {
// This is used for color mode continuity between the main Solidity Lang site and the docs
var colorSchemeParam = urlParams.get("color");
// If present, overwrite prefersDark accordingly
if (colorSchemeParam) {
prefersDark = colorSchemeParam == DARK;
}
// Remove "color" search param from URL
const { location, title } = document;
const { pathname, origin, search, hash } = location;
const newSearchParams = new URLSearchParams(search);
newSearchParams.delete("color");
const sanitizedSearch =
newSearchParams.size < 1 ? "" : "?" + newSearchParams.toString();
window.history.replaceState(
origin,
title,
pathname + sanitizedSearch + hash
);
}
// In case none existed, establish localStorage color scheme preference
var mode = prefersDark ? DARK : LIGHT;
localStorage.setItem(LS_COLOR_SCHEME, mode);
// Select the root element and set the style attribute to denote color-scheme attribute
document
.querySelector(":root")
.setAttribute("style", `--color-scheme: ${mode}`);
// NOTE: Since RTD migration to addons, the elements below are no longer present in the DOM.
// The following code is kept for compatibility with older versions.
// Remove old input and RTD logo anchor element
document.querySelector("input[name=mode]")?.remove();
document.querySelector("label[for=switch]")?.remove();
document.querySelector(".wy-side-nav-search > a")?.remove();
// Add footer note
addFooterNote();
// Build header
buildHeader();
// Close menu
toggleMenu({ force: false });
// Update active nav link
updateActiveNavLink();
// Update GitHub edit path to direct to `develop` branch
updateGitHubEditPath();
}
document.addEventListener("DOMContentLoaded", initialize);
const handleClick = (e) => {
if (e.target.closest(".backdrop")) {
toggleMenu({ force: false });
}
if (e.target.closest("a")) {
const target = e.target.closest("a");
const href = target.getAttribute("href");
if (href.includes(SOLIDITY_HOME_URL)) {
const url = new URL(href);
const params = new URLSearchParams(url.search);
params.set("color", localStorage.getItem(LS_COLOR_SCHEME));
url.search = params.toString();
target.setAttribute("href", url.toString());
}
}
};
document.addEventListener("click", handleClick);
const handleKeyDown = (e) => {
if (e.metaKey && e.key === "k") {
document.querySelector("#rtd-search-form input")?.focus();
} else if (e.key === "Escape") {
toggleMenu({ force: false });
}
if (e.metaKey && e.code === "Backslash") {
toggleColorMode();
}
};
document.addEventListener("keydown", handleKeyDown);