2021-03-19 16:33:27 +00:00
|
|
|
|
// ignore-tidy-filelength
|
2018-12-04 21:59:27 +00:00
|
|
|
|
// Local js definitions:
|
2021-01-23 13:55:24 +00:00
|
|
|
|
/* global addClass, getSettingValue, hasClass */
|
|
|
|
|
/* global onEach, onEachLazy, hasOwnProperty, removeClass, updateLocalStorage */
|
2021-03-05 15:09:46 +00:00
|
|
|
|
/* global switchTheme, useSystemTheme */
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2018-11-06 00:40:12 +00:00
|
|
|
|
if (!String.prototype.startsWith) {
|
|
|
|
|
String.prototype.startsWith = function(searchString, position) {
|
|
|
|
|
position = position || 0;
|
|
|
|
|
return this.indexOf(searchString, position) === position;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (!String.prototype.endsWith) {
|
|
|
|
|
String.prototype.endsWith = function(suffix, length) {
|
|
|
|
|
var l = length || this.length;
|
|
|
|
|
return this.indexOf(suffix, l - suffix.length) !== -1;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (!DOMTokenList.prototype.add) {
|
|
|
|
|
DOMTokenList.prototype.add = function(className) {
|
|
|
|
|
if (className && !hasClass(this, className)) {
|
|
|
|
|
if (this.className && this.className.length > 0) {
|
|
|
|
|
this.className += " " + className;
|
|
|
|
|
} else {
|
|
|
|
|
this.className = className;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!DOMTokenList.prototype.remove) {
|
|
|
|
|
DOMTokenList.prototype.remove = function(className) {
|
|
|
|
|
if (className && this.className) {
|
|
|
|
|
this.className = (" " + this.className + " ").replace(" " + className + " ", " ")
|
|
|
|
|
.trim();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-18 11:03:53 +00:00
|
|
|
|
(function () {
|
|
|
|
|
var rustdocVars = document.getElementById("rustdoc-vars");
|
|
|
|
|
if (rustdocVars) {
|
|
|
|
|
window.rootPath = rustdocVars.attributes["data-root-path"].value;
|
|
|
|
|
window.currentCrate = rustdocVars.attributes["data-current-crate"].value;
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
window.searchJS = rustdocVars.attributes["data-search-js"].value;
|
2021-01-18 11:03:53 +00:00
|
|
|
|
}
|
|
|
|
|
var sidebarVars = document.getElementById("sidebar-vars");
|
|
|
|
|
if (sidebarVars) {
|
|
|
|
|
window.sidebarCurrent = {
|
|
|
|
|
name: sidebarVars.attributes["data-name"].value,
|
|
|
|
|
ty: sidebarVars.attributes["data-ty"].value,
|
|
|
|
|
relpath: sidebarVars.attributes["data-relpath"].value,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}());
|
2020-11-08 13:49:29 +00:00
|
|
|
|
|
|
|
|
|
// Gets the human-readable string for the virtual-key code of the
|
|
|
|
|
// given KeyboardEvent, ev.
|
|
|
|
|
//
|
|
|
|
|
// This function is meant as a polyfill for KeyboardEvent#key,
|
2020-11-08 16:12:03 +00:00
|
|
|
|
// since it is not supported in IE 11 or Chrome for Android. We also test for
|
2020-11-08 13:49:29 +00:00
|
|
|
|
// KeyboardEvent#keyCode because the handleShortcut handler is
|
|
|
|
|
// also registered for the keydown event, because Blink doesn't fire
|
|
|
|
|
// keypress on hitting the Escape key.
|
|
|
|
|
//
|
|
|
|
|
// So I guess you could say things are getting pretty interoperable.
|
|
|
|
|
function getVirtualKey(ev) {
|
|
|
|
|
if ("key" in ev && typeof ev.key != "undefined") {
|
|
|
|
|
return ev.key;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var c = ev.charCode || ev.keyCode;
|
|
|
|
|
if (c == 27) {
|
|
|
|
|
return "Escape";
|
|
|
|
|
}
|
|
|
|
|
return String.fromCharCode(c);
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-09 15:04:28 +00:00
|
|
|
|
function getSearchInput() {
|
|
|
|
|
return document.getElementsByClassName("search-input")[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getSearchElement() {
|
|
|
|
|
return document.getElementById("search");
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-05 15:19:58 +00:00
|
|
|
|
var THEME_PICKER_ELEMENT_ID = "theme-picker";
|
|
|
|
|
var THEMES_ELEMENT_ID = "theme-choices";
|
2021-03-05 15:16:03 +00:00
|
|
|
|
|
2020-10-30 21:27:00 +00:00
|
|
|
|
function getThemesElement() {
|
2021-03-05 15:19:58 +00:00
|
|
|
|
return document.getElementById(THEMES_ELEMENT_ID);
|
2020-10-30 21:27:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getThemePickerElement() {
|
2021-03-05 15:19:58 +00:00
|
|
|
|
return document.getElementById(THEME_PICKER_ELEMENT_ID);
|
2020-10-30 21:27:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-25 12:21:12 +00:00
|
|
|
|
// Returns the current URL without any query parameter or hash.
|
|
|
|
|
function getNakedUrl() {
|
|
|
|
|
return window.location.href.split("?")[0].split("#")[0];
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 12:06:21 +00:00
|
|
|
|
// Sets the focus on the search bar at the top of the page
|
|
|
|
|
function focusSearchBar() {
|
|
|
|
|
getSearchInput().focus();
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-17 19:24:50 +00:00
|
|
|
|
// Removes the focus from the search bar.
|
2020-05-17 12:06:21 +00:00
|
|
|
|
function defocusSearchBar() {
|
|
|
|
|
getSearchInput().blur();
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-05 15:09:46 +00:00
|
|
|
|
function showThemeButtonState() {
|
|
|
|
|
var themePicker = getThemePickerElement();
|
|
|
|
|
var themeChoices = getThemesElement();
|
|
|
|
|
|
|
|
|
|
themeChoices.style.display = "block";
|
|
|
|
|
themePicker.style.borderBottomRightRadius = "0";
|
|
|
|
|
themePicker.style.borderBottomLeftRadius = "0";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function hideThemeButtonState() {
|
|
|
|
|
var themePicker = getThemePickerElement();
|
|
|
|
|
var themeChoices = getThemesElement();
|
|
|
|
|
|
|
|
|
|
themeChoices.style.display = "none";
|
|
|
|
|
themePicker.style.borderBottomRightRadius = "3px";
|
|
|
|
|
themePicker.style.borderBottomLeftRadius = "3px";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set up the theme picker list.
|
|
|
|
|
(function () {
|
|
|
|
|
var themeChoices = getThemesElement();
|
|
|
|
|
var themePicker = getThemePickerElement();
|
|
|
|
|
var availableThemes/* INSERT THEMES HERE */;
|
|
|
|
|
|
|
|
|
|
function switchThemeButtonState() {
|
|
|
|
|
if (themeChoices.style.display === "block") {
|
|
|
|
|
hideThemeButtonState();
|
|
|
|
|
} else {
|
|
|
|
|
showThemeButtonState();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleThemeButtonsBlur(e) {
|
|
|
|
|
var active = document.activeElement;
|
|
|
|
|
var related = e.relatedTarget;
|
|
|
|
|
|
2021-03-05 15:19:58 +00:00
|
|
|
|
if (active.id !== THEME_PICKER_ELEMENT_ID &&
|
|
|
|
|
(!active.parentNode || active.parentNode.id !== THEMES_ELEMENT_ID) &&
|
2021-03-05 15:09:46 +00:00
|
|
|
|
(!related ||
|
2021-03-05 15:19:58 +00:00
|
|
|
|
(related.id !== THEME_PICKER_ELEMENT_ID &&
|
|
|
|
|
(!related.parentNode || related.parentNode.id !== THEMES_ELEMENT_ID)))) {
|
2021-03-05 15:09:46 +00:00
|
|
|
|
hideThemeButtonState();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
themePicker.onclick = switchThemeButtonState;
|
|
|
|
|
themePicker.onblur = handleThemeButtonsBlur;
|
|
|
|
|
availableThemes.forEach(function(item) {
|
|
|
|
|
var but = document.createElement("button");
|
|
|
|
|
but.textContent = item;
|
|
|
|
|
but.onclick = function() {
|
|
|
|
|
switchTheme(window.currentTheme, window.mainTheme, item, true);
|
|
|
|
|
useSystemTheme(false);
|
|
|
|
|
};
|
|
|
|
|
but.onblur = handleThemeButtonsBlur;
|
|
|
|
|
themeChoices.appendChild(but);
|
|
|
|
|
});
|
|
|
|
|
}());
|
|
|
|
|
|
2014-01-10 04:59:53 +00:00
|
|
|
|
(function() {
|
2013-09-19 05:18:38 +00:00
|
|
|
|
"use strict";
|
|
|
|
|
|
2015-03-05 07:35:43 +00:00
|
|
|
|
// This mapping table should match the discriminants of
|
|
|
|
|
// `rustdoc::html::item_type::ItemType` type in Rust.
|
|
|
|
|
var itemTypes = ["mod",
|
|
|
|
|
"externcrate",
|
|
|
|
|
"import",
|
|
|
|
|
"struct",
|
|
|
|
|
"enum",
|
|
|
|
|
"fn",
|
|
|
|
|
"type",
|
|
|
|
|
"static",
|
|
|
|
|
"trait",
|
|
|
|
|
"impl",
|
|
|
|
|
"tymethod",
|
|
|
|
|
"method",
|
|
|
|
|
"structfield",
|
|
|
|
|
"variant",
|
|
|
|
|
"macro",
|
|
|
|
|
"primitive",
|
|
|
|
|
"associatedtype",
|
2015-05-08 22:03:42 +00:00
|
|
|
|
"constant",
|
2016-08-10 18:00:17 +00:00
|
|
|
|
"associatedconstant",
|
2017-11-15 09:31:23 +00:00
|
|
|
|
"union",
|
2018-05-28 19:30:01 +00:00
|
|
|
|
"foreigntype",
|
2018-09-25 19:56:43 +00:00
|
|
|
|
"keyword",
|
|
|
|
|
"existential",
|
|
|
|
|
"attr",
|
2019-02-07 00:02:23 +00:00
|
|
|
|
"derive",
|
|
|
|
|
"traitalias"];
|
2015-03-05 07:35:43 +00:00
|
|
|
|
|
2020-09-23 21:14:43 +00:00
|
|
|
|
var disableShortcuts = getSettingValue("disable-shortcuts") === "true";
|
2019-09-09 15:04:28 +00:00
|
|
|
|
var search_input = getSearchInput();
|
2020-05-28 12:51:12 +00:00
|
|
|
|
var searchTimeout = null;
|
2020-08-29 10:38:50 +00:00
|
|
|
|
var toggleAllDocsId = "toggle-all-docs";
|
2018-04-24 18:23:57 +00:00
|
|
|
|
|
2017-10-14 14:31:48 +00:00
|
|
|
|
// On the search screen, so you remain on the last tab you opened.
|
|
|
|
|
//
|
2017-12-05 22:39:50 +00:00
|
|
|
|
// 0 for "In Names"
|
|
|
|
|
// 1 for "In Parameters"
|
|
|
|
|
// 2 for "In Return Types"
|
2017-10-14 14:31:48 +00:00
|
|
|
|
var currentTab = 0;
|
|
|
|
|
|
2020-06-02 02:18:38 +00:00
|
|
|
|
var mouseMovedAfterSearch = true;
|
|
|
|
|
|
2018-08-15 18:08:25 +00:00
|
|
|
|
var titleBeforeSearch = document.title;
|
2020-11-10 14:01:01 +00:00
|
|
|
|
var searchTitle = null;
|
2018-08-15 18:08:25 +00:00
|
|
|
|
|
2020-05-31 12:27:33 +00:00
|
|
|
|
function clearInputTimeout() {
|
|
|
|
|
if (searchTimeout !== null) {
|
|
|
|
|
clearTimeout(searchTimeout);
|
|
|
|
|
searchTimeout = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-04 14:16:53 +00:00
|
|
|
|
function getPageId() {
|
2020-03-30 11:59:10 +00:00
|
|
|
|
if (window.location.hash) {
|
|
|
|
|
var tmp = window.location.hash.replace(/^#/, "");
|
|
|
|
|
if (tmp.length > 0) {
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
2018-04-04 14:16:53 +00:00
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-05 23:42:33 +00:00
|
|
|
|
function showSidebar() {
|
2017-12-07 21:55:14 +00:00
|
|
|
|
var elems = document.getElementsByClassName("sidebar-elems")[0];
|
|
|
|
|
if (elems) {
|
2017-12-19 23:44:44 +00:00
|
|
|
|
addClass(elems, "show-it");
|
2017-12-07 21:55:14 +00:00
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var sidebar = document.getElementsByClassName("sidebar")[0];
|
2017-12-19 23:44:44 +00:00
|
|
|
|
if (sidebar) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
addClass(sidebar, "mobile");
|
2017-12-19 23:44:44 +00:00
|
|
|
|
var filler = document.getElementById("sidebar-filler");
|
|
|
|
|
if (!filler) {
|
|
|
|
|
var div = document.createElement("div");
|
|
|
|
|
div.id = "sidebar-filler";
|
|
|
|
|
sidebar.appendChild(div);
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-12-05 23:42:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function hideSidebar() {
|
2017-12-07 21:55:14 +00:00
|
|
|
|
var elems = document.getElementsByClassName("sidebar-elems")[0];
|
|
|
|
|
if (elems) {
|
2017-12-19 23:44:44 +00:00
|
|
|
|
removeClass(elems, "show-it");
|
2017-12-07 21:55:14 +00:00
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var sidebar = document.getElementsByClassName("sidebar")[0];
|
|
|
|
|
removeClass(sidebar, "mobile");
|
2017-12-19 23:44:44 +00:00
|
|
|
|
var filler = document.getElementById("sidebar-filler");
|
|
|
|
|
if (filler) {
|
|
|
|
|
filler.remove();
|
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
document.getElementsByTagName("body")[0].style.marginTop = "";
|
2017-12-05 23:42:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-12-22 14:42:10 +00:00
|
|
|
|
function showSearchResults(search) {
|
|
|
|
|
if (search === null || typeof search === 'undefined') {
|
|
|
|
|
search = getSearchElement();
|
|
|
|
|
}
|
|
|
|
|
addClass(main, "hidden");
|
|
|
|
|
removeClass(search, "hidden");
|
2020-06-02 02:18:38 +00:00
|
|
|
|
mouseMovedAfterSearch = false;
|
2020-11-10 14:01:01 +00:00
|
|
|
|
document.title = searchTitle;
|
2019-12-22 14:42:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function hideSearchResults(search) {
|
|
|
|
|
if (search === null || typeof search === 'undefined') {
|
|
|
|
|
search = getSearchElement();
|
|
|
|
|
}
|
|
|
|
|
addClass(search, "hidden");
|
|
|
|
|
removeClass(main, "hidden");
|
2020-11-10 14:01:01 +00:00
|
|
|
|
document.title = titleBeforeSearch;
|
2021-02-17 19:24:50 +00:00
|
|
|
|
// We also remove the query parameter from the URL.
|
|
|
|
|
if (browserSupportsHistoryApi()) {
|
|
|
|
|
history.replaceState("", window.currentCrate + " - Rust",
|
|
|
|
|
getNakedUrl() + window.location.hash);
|
|
|
|
|
}
|
2019-12-22 14:42:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-22 12:15:35 +00:00
|
|
|
|
// used for special search precedence
|
|
|
|
|
var TY_PRIMITIVE = itemTypes.indexOf("primitive");
|
2018-05-28 19:30:01 +00:00
|
|
|
|
var TY_KEYWORD = itemTypes.indexOf("keyword");
|
2015-05-22 12:15:35 +00:00
|
|
|
|
|
2014-01-23 01:44:27 +00:00
|
|
|
|
function getQueryStringParams() {
|
|
|
|
|
var params = {};
|
|
|
|
|
window.location.search.substring(1).split("&").
|
|
|
|
|
map(function(s) {
|
|
|
|
|
var pair = s.split("=");
|
|
|
|
|
params[decodeURIComponent(pair[0])] =
|
2017-11-23 20:19:48 +00:00
|
|
|
|
typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]);
|
2014-01-23 01:44:27 +00:00
|
|
|
|
});
|
|
|
|
|
return params;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function browserSupportsHistoryApi() {
|
2019-01-10 22:59:42 +00:00
|
|
|
|
return window.history && typeof window.history.pushState === "function";
|
2014-01-23 01:44:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 16:41:40 +00:00
|
|
|
|
function isHidden(elem) {
|
|
|
|
|
return elem.offsetHeight === 0;
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-26 16:17:38 +00:00
|
|
|
|
var main = document.getElementById("main");
|
2019-11-05 16:41:40 +00:00
|
|
|
|
var savedHash = "";
|
2018-11-26 16:17:38 +00:00
|
|
|
|
|
2019-11-05 16:41:40 +00:00
|
|
|
|
function handleHashes(ev) {
|
2020-05-17 13:34:59 +00:00
|
|
|
|
var elem;
|
2019-11-04 12:14:36 +00:00
|
|
|
|
var search = getSearchElement();
|
|
|
|
|
if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
|
2019-11-05 16:41:40 +00:00
|
|
|
|
// This block occurs when clicking on an element in the navbar while
|
|
|
|
|
// in a search.
|
2019-12-22 14:42:10 +00:00
|
|
|
|
hideSearchResults(search);
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var hash = ev.newURL.slice(ev.newURL.indexOf("#") + 1);
|
2017-11-10 18:40:46 +00:00
|
|
|
|
if (browserSupportsHistoryApi()) {
|
2021-01-25 12:21:12 +00:00
|
|
|
|
// `window.location.search`` contains all the query parameters, not just `search`.
|
|
|
|
|
history.replaceState(hash, "",
|
|
|
|
|
getNakedUrl() + window.location.search + "#" + hash);
|
2017-11-10 18:40:46 +00:00
|
|
|
|
}
|
2020-05-17 13:34:59 +00:00
|
|
|
|
elem = document.getElementById(hash);
|
2017-11-06 20:14:37 +00:00
|
|
|
|
if (elem) {
|
|
|
|
|
elem.scrollIntoView();
|
|
|
|
|
}
|
2013-10-02 17:32:13 +00:00
|
|
|
|
}
|
2019-11-05 16:41:40 +00:00
|
|
|
|
// This part is used in case an element is not visible.
|
|
|
|
|
if (savedHash !== window.location.hash) {
|
|
|
|
|
savedHash = window.location.hash;
|
|
|
|
|
if (savedHash.length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-05-17 13:34:59 +00:00
|
|
|
|
elem = document.getElementById(savedHash.slice(1)); // we remove the '#'
|
2019-11-05 16:41:40 +00:00
|
|
|
|
if (!elem || !isHidden(elem)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var parent = elem.parentNode;
|
|
|
|
|
if (parent && hasClass(parent, "impl-items")) {
|
|
|
|
|
// In case this is a trait implementation item, we first need to toggle
|
|
|
|
|
// the "Show hidden undocumented items".
|
|
|
|
|
onEachLazy(parent.getElementsByClassName("collapsed"), function(e) {
|
|
|
|
|
if (e.parentNode === parent) {
|
|
|
|
|
// Only click on the toggle we're looking for.
|
|
|
|
|
e.click();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (isHidden(elem)) {
|
|
|
|
|
// The whole parent is collapsed. We need to click on its toggle as well!
|
|
|
|
|
if (hasClass(parent.lastElementChild, "collapse-toggle")) {
|
|
|
|
|
parent.lastElementChild.click();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-10-02 17:32:13 +00:00
|
|
|
|
}
|
2018-08-23 07:43:06 +00:00
|
|
|
|
|
2019-11-04 12:14:36 +00:00
|
|
|
|
function highlightSourceLines(match, ev) {
|
|
|
|
|
if (typeof match === "undefined") {
|
|
|
|
|
// If we're in mobile mode, we should hide the sidebar in any case.
|
|
|
|
|
hideSidebar();
|
|
|
|
|
match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
|
|
|
|
|
}
|
|
|
|
|
if (!match) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var from = parseInt(match[1], 10);
|
|
|
|
|
var to = from;
|
|
|
|
|
if (typeof match[2] !== "undefined") {
|
|
|
|
|
to = parseInt(match[2], 10);
|
|
|
|
|
}
|
|
|
|
|
if (to < from) {
|
|
|
|
|
var tmp = to;
|
|
|
|
|
to = from;
|
|
|
|
|
from = tmp;
|
|
|
|
|
}
|
|
|
|
|
var elem = document.getElementById(from);
|
|
|
|
|
if (!elem) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (!ev) {
|
|
|
|
|
var x = document.getElementById(from);
|
|
|
|
|
if (x) {
|
|
|
|
|
x.scrollIntoView();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
onEachLazy(document.getElementsByClassName("line-numbers"), function(e) {
|
|
|
|
|
onEachLazy(e.getElementsByTagName("span"), function(i_e) {
|
|
|
|
|
removeClass(i_e, "line-highlighted");
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
for (var i = from; i <= to; ++i) {
|
|
|
|
|
elem = document.getElementById(i);
|
|
|
|
|
if (!elem) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
addClass(elem, "line-highlighted");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-05 16:41:40 +00:00
|
|
|
|
function onHashChange(ev) {
|
|
|
|
|
// If we're in mobile mode, we should hide the sidebar in any case.
|
|
|
|
|
hideSidebar();
|
|
|
|
|
var match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
|
|
|
|
|
if (match) {
|
|
|
|
|
return highlightSourceLines(match, ev);
|
|
|
|
|
}
|
2019-11-07 09:16:14 +00:00
|
|
|
|
handleHashes(ev);
|
2019-11-05 16:41:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-25 10:34:04 +00:00
|
|
|
|
function expandSection(id) {
|
|
|
|
|
var elem = document.getElementById(id);
|
|
|
|
|
if (elem && isHidden(elem)) {
|
2018-12-16 12:45:46 +00:00
|
|
|
|
var h3 = elem.parentNode.previousElementSibling;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (h3 && h3.tagName !== "H3") {
|
2018-12-16 12:45:46 +00:00
|
|
|
|
h3 = h3.previousElementSibling; // skip div.docblock
|
2018-08-23 07:43:06 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (h3) {
|
|
|
|
|
var collapses = h3.getElementsByClassName("collapse-toggle");
|
|
|
|
|
if (collapses.length > 0) {
|
|
|
|
|
// The element is not visible, we need to make it appear!
|
|
|
|
|
collapseDocs(collapses[0], "show");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-12 22:32:44 +00:00
|
|
|
|
function getHelpElement(build) {
|
|
|
|
|
if (build !== false) {
|
|
|
|
|
buildHelperPopup();
|
|
|
|
|
}
|
2019-09-09 15:04:28 +00:00
|
|
|
|
return document.getElementById("help");
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-08 11:38:47 +00:00
|
|
|
|
function displayHelp(display, ev, help) {
|
2017-10-14 16:43:00 +00:00
|
|
|
|
if (display === true) {
|
2020-12-12 22:32:44 +00:00
|
|
|
|
help = help ? help : getHelpElement(true);
|
2017-10-14 16:43:00 +00:00
|
|
|
|
if (hasClass(help, "hidden")) {
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
removeClass(help, "hidden");
|
|
|
|
|
addClass(document.body, "blur");
|
|
|
|
|
}
|
2020-12-12 22:32:44 +00:00
|
|
|
|
} else {
|
|
|
|
|
// No need to build the help popup if we want to hide it in case it hasn't been
|
|
|
|
|
// built yet...
|
|
|
|
|
help = help ? help : getHelpElement(false);
|
|
|
|
|
if (help && hasClass(help, "hidden") === false) {
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
addClass(help, "hidden");
|
|
|
|
|
removeClass(document.body, "blur");
|
|
|
|
|
}
|
2017-10-14 16:43:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-09 15:04:28 +00:00
|
|
|
|
function handleEscape(ev) {
|
2020-12-12 22:32:44 +00:00
|
|
|
|
var help = getHelpElement(false);
|
2019-09-09 15:04:28 +00:00
|
|
|
|
var search = getSearchElement();
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (hasClass(help, "hidden") === false) {
|
2019-02-08 11:38:47 +00:00
|
|
|
|
displayHelp(false, ev, help);
|
2018-11-16 15:31:07 +00:00
|
|
|
|
} else if (hasClass(search, "hidden") === false) {
|
2020-05-31 12:27:33 +00:00
|
|
|
|
clearInputTimeout();
|
2018-03-18 15:32:41 +00:00
|
|
|
|
ev.preventDefault();
|
2019-12-22 14:42:10 +00:00
|
|
|
|
hideSearchResults(search);
|
2018-03-05 22:37:33 +00:00
|
|
|
|
}
|
2018-03-18 15:32:41 +00:00
|
|
|
|
defocusSearchBar();
|
2020-10-30 20:03:01 +00:00
|
|
|
|
hideThemeButtonState();
|
2018-03-18 15:32:41 +00:00
|
|
|
|
}
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2018-03-18 15:32:41 +00:00
|
|
|
|
function handleShortcut(ev) {
|
2015-11-05 10:39:02 +00:00
|
|
|
|
// Don't interfere with browser shortcuts
|
2019-10-21 09:36:52 +00:00
|
|
|
|
if (ev.ctrlKey || ev.altKey || ev.metaKey || disableShortcuts === true) {
|
2015-11-05 10:39:02 +00:00
|
|
|
|
return;
|
2018-03-05 22:37:33 +00:00
|
|
|
|
}
|
2015-11-05 10:39:02 +00:00
|
|
|
|
|
2018-03-18 15:32:41 +00:00
|
|
|
|
if (document.activeElement.tagName === "INPUT") {
|
|
|
|
|
switch (getVirtualKey(ev)) {
|
|
|
|
|
case "Escape":
|
2019-09-09 15:04:28 +00:00
|
|
|
|
handleEscape(ev);
|
2018-03-18 15:32:41 +00:00
|
|
|
|
break;
|
2015-04-11 22:32:53 +00:00
|
|
|
|
}
|
2018-03-18 15:32:41 +00:00
|
|
|
|
} else {
|
|
|
|
|
switch (getVirtualKey(ev)) {
|
|
|
|
|
case "Escape":
|
2019-09-09 15:04:28 +00:00
|
|
|
|
handleEscape(ev);
|
2018-03-18 15:32:41 +00:00
|
|
|
|
break;
|
2015-07-07 14:15:22 +00:00
|
|
|
|
|
2018-03-18 15:32:41 +00:00
|
|
|
|
case "s":
|
|
|
|
|
case "S":
|
2019-09-09 15:04:28 +00:00
|
|
|
|
displayHelp(false, ev);
|
2018-03-18 15:32:41 +00:00
|
|
|
|
ev.preventDefault();
|
|
|
|
|
focusSearchBar();
|
|
|
|
|
break;
|
2015-07-07 14:15:22 +00:00
|
|
|
|
|
2018-03-18 15:32:41 +00:00
|
|
|
|
case "+":
|
|
|
|
|
case "-":
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
toggleAllDocs();
|
|
|
|
|
break;
|
2016-05-21 02:21:35 +00:00
|
|
|
|
|
2018-03-18 15:32:41 +00:00
|
|
|
|
case "?":
|
2020-08-11 09:30:50 +00:00
|
|
|
|
displayHelp(true, ev);
|
2018-03-18 15:32:41 +00:00
|
|
|
|
break;
|
2020-10-30 21:27:00 +00:00
|
|
|
|
|
2020-11-05 13:24:45 +00:00
|
|
|
|
case "t":
|
|
|
|
|
case "T":
|
|
|
|
|
displayHelp(false, ev);
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
var themePicker = getThemePickerElement();
|
|
|
|
|
themePicker.click();
|
|
|
|
|
themePicker.focus();
|
|
|
|
|
break;
|
|
|
|
|
|
2020-10-30 21:27:00 +00:00
|
|
|
|
default:
|
2021-03-05 15:16:03 +00:00
|
|
|
|
if (getThemePickerElement().parentNode.contains(ev.target)) {
|
2020-10-30 21:27:00 +00:00
|
|
|
|
handleThemeKeyDown(ev);
|
|
|
|
|
}
|
2013-09-27 18:06:07 +00:00
|
|
|
|
}
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
2015-07-07 14:15:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-30 21:27:00 +00:00
|
|
|
|
function handleThemeKeyDown(ev) {
|
|
|
|
|
var active = document.activeElement;
|
|
|
|
|
var themes = getThemesElement();
|
|
|
|
|
switch (getVirtualKey(ev)) {
|
|
|
|
|
case "ArrowUp":
|
|
|
|
|
ev.preventDefault();
|
2021-03-05 15:19:58 +00:00
|
|
|
|
if (active.previousElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
|
2020-10-30 21:27:00 +00:00
|
|
|
|
active.previousElementSibling.focus();
|
|
|
|
|
} else {
|
|
|
|
|
showThemeButtonState();
|
|
|
|
|
themes.lastElementChild.focus();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "ArrowDown":
|
|
|
|
|
ev.preventDefault();
|
2021-03-05 15:19:58 +00:00
|
|
|
|
if (active.nextElementSibling && ev.target.id !== THEME_PICKER_ELEMENT_ID) {
|
2020-10-30 21:27:00 +00:00
|
|
|
|
active.nextElementSibling.focus();
|
|
|
|
|
} else {
|
|
|
|
|
showThemeButtonState();
|
|
|
|
|
themes.firstElementChild.focus();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "Enter":
|
|
|
|
|
case "Return":
|
|
|
|
|
case "Space":
|
2021-03-05 15:19:58 +00:00
|
|
|
|
if (ev.target.id === THEME_PICKER_ELEMENT_ID && themes.style.display === "none") {
|
2020-10-30 21:27:00 +00:00
|
|
|
|
ev.preventDefault();
|
|
|
|
|
showThemeButtonState();
|
|
|
|
|
themes.firstElementChild.focus();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case "Home":
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
themes.firstElementChild.focus();
|
|
|
|
|
break;
|
|
|
|
|
case "End":
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
themes.lastElementChild.focus();
|
|
|
|
|
break;
|
|
|
|
|
// The escape key is handled in handleEscape, not here,
|
|
|
|
|
// so that pressing escape will close the menu even if it isn't focused
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-25 10:34:04 +00:00
|
|
|
|
function findParentElement(elem, tagName) {
|
|
|
|
|
do {
|
|
|
|
|
if (elem && elem.tagName === tagName) {
|
|
|
|
|
return elem;
|
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
elem = elem.parentNode;
|
|
|
|
|
} while (elem);
|
2018-08-25 10:34:04 +00:00
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-22 13:14:37 +00:00
|
|
|
|
document.addEventListener("keypress", handleShortcut);
|
|
|
|
|
document.addEventListener("keydown", handleShortcut);
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2020-12-31 12:21:50 +00:00
|
|
|
|
document.addEventListener("mousemove", function() { mouseMovedAfterSearch = true; });
|
2020-06-02 02:18:38 +00:00
|
|
|
|
|
2019-11-15 01:02:09 +00:00
|
|
|
|
var handleSourceHighlight = (function() {
|
|
|
|
|
var prev_line_id = 0;
|
|
|
|
|
|
|
|
|
|
var set_fragment = function(name) {
|
2019-11-15 01:30:44 +00:00
|
|
|
|
var x = window.scrollX,
|
|
|
|
|
y = window.scrollY;
|
2019-11-15 01:02:09 +00:00
|
|
|
|
if (browserSupportsHistoryApi()) {
|
|
|
|
|
history.replaceState(null, null, "#" + name);
|
|
|
|
|
highlightSourceLines();
|
|
|
|
|
} else {
|
|
|
|
|
location.replace("#" + name);
|
|
|
|
|
}
|
2019-11-15 01:30:44 +00:00
|
|
|
|
// Prevent jumps when selecting one or many lines
|
|
|
|
|
window.scrollTo(x, y);
|
2019-11-15 01:02:09 +00:00
|
|
|
|
};
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2019-11-15 01:02:09 +00:00
|
|
|
|
return function(ev) {
|
|
|
|
|
var cur_line_id = parseInt(ev.target.id, 10);
|
2019-11-15 01:30:44 +00:00
|
|
|
|
ev.preventDefault();
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2019-11-15 01:02:09 +00:00
|
|
|
|
if (ev.shiftKey && prev_line_id) {
|
|
|
|
|
// Swap selection if needed
|
|
|
|
|
if (prev_line_id > cur_line_id) {
|
|
|
|
|
var tmp = prev_line_id;
|
|
|
|
|
prev_line_id = cur_line_id;
|
|
|
|
|
cur_line_id = tmp;
|
2017-04-14 14:37:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-15 01:02:09 +00:00
|
|
|
|
set_fragment(prev_line_id + "-" + cur_line_id);
|
2017-04-14 14:37:09 +00:00
|
|
|
|
} else {
|
2019-11-15 01:02:09 +00:00
|
|
|
|
prev_line_id = cur_line_id;
|
2017-04-14 14:37:09 +00:00
|
|
|
|
|
2019-11-15 01:02:09 +00:00
|
|
|
|
set_fragment(cur_line_id);
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
2020-05-17 13:34:59 +00:00
|
|
|
|
};
|
2020-05-17 12:49:04 +00:00
|
|
|
|
}());
|
2019-11-15 01:02:09 +00:00
|
|
|
|
|
2019-12-22 13:14:37 +00:00
|
|
|
|
document.addEventListener("click", function(ev) {
|
2020-12-12 22:32:44 +00:00
|
|
|
|
var helpElem = getHelpElement(false);
|
2020-08-10 14:42:11 +00:00
|
|
|
|
if (hasClass(ev.target, "help-button")) {
|
|
|
|
|
displayHelp(true, ev);
|
|
|
|
|
} else if (hasClass(ev.target, "collapse-toggle")) {
|
2019-11-15 01:02:09 +00:00
|
|
|
|
collapseDocs(ev.target, "toggle");
|
|
|
|
|
} else if (hasClass(ev.target.parentNode, "collapse-toggle")) {
|
|
|
|
|
collapseDocs(ev.target.parentNode, "toggle");
|
|
|
|
|
} else if (ev.target.tagName === "SPAN" && hasClass(ev.target.parentNode, "line-numbers")) {
|
|
|
|
|
handleSourceHighlight(ev);
|
2020-12-12 22:32:44 +00:00
|
|
|
|
} else if (helpElem && hasClass(helpElem, "hidden") === false) {
|
|
|
|
|
var is_inside_help_popup = ev.target !== helpElem && helpElem.contains(ev.target);
|
2019-10-23 22:37:14 +00:00
|
|
|
|
if (is_inside_help_popup === false) {
|
2020-12-12 22:32:44 +00:00
|
|
|
|
addClass(helpElem, "hidden");
|
2019-10-23 22:37:14 +00:00
|
|
|
|
removeClass(document.body, "blur");
|
|
|
|
|
}
|
2018-08-25 10:34:04 +00:00
|
|
|
|
} else {
|
|
|
|
|
// Making a collapsed element visible on onhashchange seems
|
|
|
|
|
// too late
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var a = findParentElement(ev.target, "A");
|
2018-08-25 10:34:04 +00:00
|
|
|
|
if (a && a.hash) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
expandSection(a.hash.replace(/^#/, ""));
|
2018-08-25 10:34:04 +00:00
|
|
|
|
}
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
2019-12-22 13:14:37 +00:00
|
|
|
|
});
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2020-05-17 12:49:04 +00:00
|
|
|
|
(function() {
|
|
|
|
|
var x = document.getElementsByClassName("version-selector");
|
|
|
|
|
if (x.length > 0) {
|
|
|
|
|
x[0].onchange = function() {
|
|
|
|
|
var i, match,
|
|
|
|
|
url = document.location.href,
|
|
|
|
|
stripped = "",
|
2021-01-18 11:03:53 +00:00
|
|
|
|
len = window.rootPath.match(/\.\.\//g).length + 1;
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2020-05-17 12:49:04 +00:00
|
|
|
|
for (i = 0; i < len; ++i) {
|
|
|
|
|
match = url.match(/\/[^\/]*$/);
|
|
|
|
|
if (i < len - 1) {
|
|
|
|
|
stripped = match[0] + stripped;
|
|
|
|
|
}
|
|
|
|
|
url = url.substring(0, url.length - match[0].length);
|
2017-04-14 14:37:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 09:48:59 +00:00
|
|
|
|
var selectedVersion = document.getElementsByClassName("version-selector")[0].value;
|
|
|
|
|
url += "/" + selectedVersion + stripped;
|
2017-04-14 14:37:09 +00:00
|
|
|
|
|
2020-05-17 12:49:04 +00:00
|
|
|
|
document.location.href = url;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}());
|
2015-07-07 14:15:22 +00:00
|
|
|
|
|
2014-07-03 21:07:16 +00:00
|
|
|
|
/**
|
2014-07-03 22:28:22 +00:00
|
|
|
|
* A function to compute the Levenshtein distance between two strings
|
|
|
|
|
* Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported
|
|
|
|
|
* Full License can be found at http://creativecommons.org/licenses/by-sa/3.0/legalcode
|
2014-09-06 00:35:19 +00:00
|
|
|
|
* This code is an unmodified version of the code written by Marco de Wit
|
2014-07-03 22:28:22 +00:00
|
|
|
|
* and was found at http://stackoverflow.com/a/18514751/745719
|
2014-07-03 21:07:16 +00:00
|
|
|
|
*/
|
2018-01-07 15:19:44 +00:00
|
|
|
|
var levenshtein_row2 = [];
|
|
|
|
|
function levenshtein(s1, s2) {
|
|
|
|
|
if (s1 === s2) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
var s1_len = s1.length, s2_len = s2.length;
|
|
|
|
|
if (s1_len && s2_len) {
|
|
|
|
|
var i1 = 0, i2 = 0, a, b, c, c2, row = levenshtein_row2;
|
|
|
|
|
while (i1 < s1_len) {
|
|
|
|
|
row[i1] = ++i1;
|
2015-05-22 12:14:28 +00:00
|
|
|
|
}
|
2018-01-07 15:19:44 +00:00
|
|
|
|
while (i2 < s2_len) {
|
|
|
|
|
c2 = s2.charCodeAt(i2);
|
|
|
|
|
a = i2;
|
|
|
|
|
++i2;
|
|
|
|
|
b = i2;
|
|
|
|
|
for (i1 = 0; i1 < s1_len; ++i1) {
|
|
|
|
|
c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0);
|
|
|
|
|
a = row[i1];
|
|
|
|
|
b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c);
|
|
|
|
|
row[i1] = b;
|
2014-07-03 21:07:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-07 15:19:44 +00:00
|
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
return s1_len + s2_len;
|
|
|
|
|
}
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2020-05-17 12:57:19 +00:00
|
|
|
|
window.initSearch = function(rawSearchIndex) {
|
2014-07-03 21:07:16 +00:00
|
|
|
|
var MAX_LEV_DISTANCE = 3;
|
2017-11-21 23:17:30 +00:00
|
|
|
|
var MAX_RESULTS = 200;
|
2018-06-16 18:44:55 +00:00
|
|
|
|
var GENERICS_DATA = 1;
|
|
|
|
|
var NAME = 0;
|
|
|
|
|
var INPUTS_DATA = 0;
|
|
|
|
|
var OUTPUT_DATA = 1;
|
2020-02-23 01:38:33 +00:00
|
|
|
|
var NO_TYPE_FILTER = -1;
|
|
|
|
|
var currentResults, index, searchIndex;
|
2020-05-04 12:51:06 +00:00
|
|
|
|
var ALIASES = {};
|
2014-03-16 08:08:56 +00:00
|
|
|
|
var params = getQueryStringParams();
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2014-02-21 07:15:08 +00:00
|
|
|
|
// Populate search bar with query string search term when provided,
|
|
|
|
|
// but only if the input bar is empty. This avoid the obnoxious issue
|
|
|
|
|
// where you start trying to do a search, and the index loads, and
|
|
|
|
|
// suddenly your search is gone!
|
2018-04-24 18:23:57 +00:00
|
|
|
|
if (search_input.value === "") {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
search_input.value = params.search || "";
|
2014-02-21 07:15:08 +00:00
|
|
|
|
}
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2014-01-10 04:59:53 +00:00
|
|
|
|
/**
|
|
|
|
|
* Executes the query and builds an index of results
|
2018-09-30 22:47:54 +00:00
|
|
|
|
* @param {[Object]} query [The user query]
|
|
|
|
|
* @param {[type]} searchWords [The list of search words to query
|
|
|
|
|
* against]
|
|
|
|
|
* @param {[type]} filterCrates [Crate to search in if defined]
|
|
|
|
|
* @return {[type]} [A search index of results]
|
2014-01-10 04:59:53 +00:00
|
|
|
|
*/
|
2018-09-30 22:47:54 +00:00
|
|
|
|
function execQuery(query, searchWords, filterCrates) {
|
2018-01-07 15:19:44 +00:00
|
|
|
|
function itemTypeFromName(typename) {
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var i = 0, len = itemTypes.length; i < len; ++i) {
|
2018-01-07 15:19:44 +00:00
|
|
|
|
if (itemTypes[i] === typename) {
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-23 01:38:33 +00:00
|
|
|
|
return NO_TYPE_FILTER;
|
2018-01-07 15:19:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-19 05:18:38 +00:00
|
|
|
|
var valLower = query.query.toLowerCase(),
|
|
|
|
|
val = valLower,
|
2014-04-09 07:49:31 +00:00
|
|
|
|
typeFilter = itemTypeFromName(query.type),
|
2017-11-21 23:17:30 +00:00
|
|
|
|
results = {}, results_in_args = {}, results_returned = {},
|
2014-01-10 04:59:53 +00:00
|
|
|
|
split = valLower.split("::");
|
|
|
|
|
|
2021-01-01 00:51:46 +00:00
|
|
|
|
split = split.filter(function(segment) { return segment !== ""; });
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2017-11-21 23:17:30 +00:00
|
|
|
|
function transformResults(results, isType) {
|
|
|
|
|
var out = [];
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var i = 0, len = results.length; i < len; ++i) {
|
2017-11-21 23:17:30 +00:00
|
|
|
|
if (results[i].id > -1) {
|
|
|
|
|
var obj = searchIndex[results[i].id];
|
|
|
|
|
obj.lev = results[i].lev;
|
|
|
|
|
if (isType !== true || obj.type) {
|
2018-04-25 22:36:00 +00:00
|
|
|
|
var res = buildHrefAndPath(obj);
|
|
|
|
|
obj.displayPath = pathSplitter(res[0]);
|
2018-05-12 12:57:52 +00:00
|
|
|
|
obj.fullPath = obj.displayPath + obj.name;
|
2018-06-16 12:14:18 +00:00
|
|
|
|
// To be sure than it some items aren't considered as duplicate.
|
2018-11-16 15:31:07 +00:00
|
|
|
|
obj.fullPath += "|" + obj.ty;
|
2018-04-25 22:36:00 +00:00
|
|
|
|
obj.href = res[1];
|
2017-11-21 23:17:30 +00:00
|
|
|
|
out.push(obj);
|
2018-04-25 22:36:00 +00:00
|
|
|
|
if (out.length >= MAX_RESULTS) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2017-11-21 23:17:30 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function sortResults(results, isType) {
|
|
|
|
|
var ar = [];
|
|
|
|
|
for (var entry in results) {
|
2020-05-17 13:34:59 +00:00
|
|
|
|
if (hasOwnProperty(results, entry)) {
|
2017-11-21 23:17:30 +00:00
|
|
|
|
ar.push(results[entry]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
results = ar;
|
2020-12-30 15:36:08 +00:00
|
|
|
|
var i, len, result;
|
|
|
|
|
for (i = 0, len = results.length; i < len; ++i) {
|
|
|
|
|
result = results[i];
|
|
|
|
|
result.word = searchWords[result.id];
|
|
|
|
|
result.item = searchIndex[result.id] || {};
|
2017-11-21 23:17:30 +00:00
|
|
|
|
}
|
|
|
|
|
// if there are no results then return to default and fail
|
|
|
|
|
if (results.length === 0) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
results.sort(function(aaa, bbb) {
|
|
|
|
|
var a, b;
|
|
|
|
|
|
2019-09-02 13:03:35 +00:00
|
|
|
|
// sort by exact match with regard to the last word (mismatch goes later)
|
|
|
|
|
a = (aaa.word !== val);
|
|
|
|
|
b = (bbb.word !== val);
|
|
|
|
|
if (a !== b) { return a - b; }
|
|
|
|
|
|
2017-11-21 23:17:30 +00:00
|
|
|
|
// Sort by non levenshtein results and then levenshtein results by the distance
|
|
|
|
|
// (less changes required to match means higher rankings)
|
|
|
|
|
a = (aaa.lev);
|
|
|
|
|
b = (bbb.lev);
|
|
|
|
|
if (a !== b) { return a - b; }
|
|
|
|
|
|
|
|
|
|
// sort by crate (non-current crate goes later)
|
|
|
|
|
a = (aaa.item.crate !== window.currentCrate);
|
|
|
|
|
b = (bbb.item.crate !== window.currentCrate);
|
|
|
|
|
if (a !== b) { return a - b; }
|
|
|
|
|
|
|
|
|
|
// sort by item name length (longer goes later)
|
|
|
|
|
a = aaa.word.length;
|
|
|
|
|
b = bbb.word.length;
|
|
|
|
|
if (a !== b) { return a - b; }
|
|
|
|
|
|
|
|
|
|
// sort by item name (lexicographically larger goes later)
|
|
|
|
|
a = aaa.word;
|
|
|
|
|
b = bbb.word;
|
|
|
|
|
if (a !== b) { return (a > b ? +1 : -1); }
|
|
|
|
|
|
|
|
|
|
// sort by index of keyword in item name (no literal occurrence goes later)
|
|
|
|
|
a = (aaa.index < 0);
|
|
|
|
|
b = (bbb.index < 0);
|
|
|
|
|
if (a !== b) { return a - b; }
|
|
|
|
|
// (later literal occurrence, if any, goes later)
|
|
|
|
|
a = aaa.index;
|
|
|
|
|
b = bbb.index;
|
|
|
|
|
if (a !== b) { return a - b; }
|
|
|
|
|
|
2018-05-28 19:30:01 +00:00
|
|
|
|
// special precedence for primitive and keyword pages
|
|
|
|
|
if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
|
|
|
|
|
(aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
|
2017-11-21 23:17:30 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
2018-05-28 19:30:01 +00:00
|
|
|
|
if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
|
|
|
|
|
(bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
|
2017-11-21 23:17:30 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sort by description (no description goes later)
|
2018-11-16 15:31:07 +00:00
|
|
|
|
a = (aaa.item.desc === "");
|
|
|
|
|
b = (bbb.item.desc === "");
|
2017-11-21 23:17:30 +00:00
|
|
|
|
if (a !== b) { return a - b; }
|
|
|
|
|
|
|
|
|
|
// sort by type (later occurrence in `itemTypes` goes later)
|
|
|
|
|
a = aaa.item.ty;
|
|
|
|
|
b = bbb.item.ty;
|
|
|
|
|
if (a !== b) { return a - b; }
|
|
|
|
|
|
|
|
|
|
// sort by path (lexicographically larger goes later)
|
|
|
|
|
a = aaa.item.path;
|
|
|
|
|
b = bbb.item.path;
|
|
|
|
|
if (a !== b) { return (a > b ? +1 : -1); }
|
|
|
|
|
|
|
|
|
|
// que sera, sera
|
|
|
|
|
return 0;
|
|
|
|
|
});
|
|
|
|
|
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (i = 0, len = results.length; i < len; ++i) {
|
2017-11-21 23:17:30 +00:00
|
|
|
|
var result = results[i];
|
|
|
|
|
|
|
|
|
|
// this validation does not make sense when searching by types
|
|
|
|
|
if (result.dontValidate) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
var name = result.item.name.toLowerCase(),
|
|
|
|
|
path = result.item.path.toLowerCase(),
|
|
|
|
|
parent = result.item.parent;
|
|
|
|
|
|
|
|
|
|
if (isType !== true &&
|
|
|
|
|
validateResult(name, path, split, parent) === false)
|
|
|
|
|
{
|
|
|
|
|
result.id = -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return transformResults(results);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-01 16:38:37 +00:00
|
|
|
|
function extractGenerics(val) {
|
|
|
|
|
val = val.toLowerCase();
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (val.indexOf("<") !== -1) {
|
|
|
|
|
var values = val.substring(val.indexOf("<") + 1, val.lastIndexOf(">"));
|
2017-11-01 16:38:37 +00:00
|
|
|
|
return {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
name: val.substring(0, val.indexOf("<")),
|
2017-11-01 16:38:37 +00:00
|
|
|
|
generics: values.split(/\s*,\s*/),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
name: val,
|
|
|
|
|
generics: [],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-13 05:59:16 +00:00
|
|
|
|
function getObjectNameFromId(id) {
|
2020-02-23 01:38:33 +00:00
|
|
|
|
if (typeof id === "number") {
|
2021-03-13 05:59:16 +00:00
|
|
|
|
return searchIndex[id].name;
|
2020-02-23 01:38:33 +00:00
|
|
|
|
}
|
2021-03-13 05:59:16 +00:00
|
|
|
|
return id;
|
2020-02-23 01:38:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-01 16:38:37 +00:00
|
|
|
|
function checkGenerics(obj, val) {
|
|
|
|
|
// The names match, but we need to be sure that all generics kinda
|
|
|
|
|
// match as well.
|
2021-03-13 16:54:19 +00:00
|
|
|
|
var tmp_lev, elem_name;
|
2017-11-01 16:38:37 +00:00
|
|
|
|
if (val.generics.length > 0) {
|
2018-06-16 18:44:55 +00:00
|
|
|
|
if (obj.length > GENERICS_DATA &&
|
|
|
|
|
obj[GENERICS_DATA].length >= val.generics.length) {
|
2021-03-13 17:28:36 +00:00
|
|
|
|
var elems = Object.create(null);
|
2021-03-13 06:23:42 +00:00
|
|
|
|
var elength = object[GENERICS_DATA].length;
|
|
|
|
|
for (var x = 0; x < elength; ++x) {
|
|
|
|
|
elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1;
|
|
|
|
|
}
|
2017-11-21 23:17:30 +00:00
|
|
|
|
var total = 0;
|
|
|
|
|
var done = 0;
|
|
|
|
|
// We need to find the type that matches the most to remove it in order
|
|
|
|
|
// to move forward.
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var vlength = val.generics.length;
|
2021-03-13 16:32:40 +00:00
|
|
|
|
for (x = 0; x < vlength; ++x) {
|
2021-03-13 06:23:42 +00:00
|
|
|
|
var lev = MAX_LEV_DISTANCE + 1;
|
|
|
|
|
var firstGeneric = getObjectNameFromId(val.generics[x]);
|
2021-03-13 16:34:37 +00:00
|
|
|
|
var match = null;
|
2021-03-13 06:23:42 +00:00
|
|
|
|
if (elems[firstGeneric]) {
|
|
|
|
|
match = firstGeneric;
|
|
|
|
|
lev = 0;
|
|
|
|
|
} else {
|
2021-03-13 16:54:19 +00:00
|
|
|
|
for (elem_name in elems) {
|
|
|
|
|
tmp_lev = levenshtein(elem_name, firstGeneric);
|
2021-03-13 06:23:42 +00:00
|
|
|
|
if (tmp_lev < lev) {
|
|
|
|
|
lev = tmp_lev;
|
|
|
|
|
match = elem_name;
|
|
|
|
|
}
|
2017-11-01 16:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-03-13 16:34:37 +00:00
|
|
|
|
if (match !== null) {
|
2021-03-13 06:23:42 +00:00
|
|
|
|
elems[match] -= 1;
|
|
|
|
|
if (elems[match] == 0) {
|
|
|
|
|
delete elems[match];
|
|
|
|
|
}
|
|
|
|
|
total += lev;
|
2017-11-21 23:17:30 +00:00
|
|
|
|
done += 1;
|
2017-11-01 16:38:37 +00:00
|
|
|
|
} else {
|
|
|
|
|
return MAX_LEV_DISTANCE + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-02-08 11:38:47 +00:00
|
|
|
|
return Math.ceil(total / done);
|
2017-11-01 16:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return MAX_LEV_DISTANCE + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for type name and type generics (if any).
|
|
|
|
|
function checkType(obj, val, literalSearch) {
|
|
|
|
|
var lev_distance = MAX_LEV_DISTANCE + 1;
|
2021-03-13 06:23:42 +00:00
|
|
|
|
var len, x, firstGeneric;
|
2018-06-16 18:44:55 +00:00
|
|
|
|
if (obj[NAME] === val.name) {
|
2017-11-01 16:38:37 +00:00
|
|
|
|
if (literalSearch === true) {
|
2018-01-22 21:49:44 +00:00
|
|
|
|
if (val.generics && val.generics.length !== 0) {
|
2018-06-16 18:44:55 +00:00
|
|
|
|
if (obj.length > GENERICS_DATA &&
|
|
|
|
|
obj[GENERICS_DATA].length >= val.generics.length) {
|
2021-03-13 17:28:36 +00:00
|
|
|
|
var elems = Object.create(null);
|
2021-03-13 06:23:42 +00:00
|
|
|
|
len = obj[GENERICS_DATA].length;
|
|
|
|
|
for (x = 0; x < len; ++x) {
|
|
|
|
|
elems[getObjectNameFromId(obj[GENERICS_DATA][x])] += 1;
|
|
|
|
|
}
|
2017-11-01 16:38:37 +00:00
|
|
|
|
|
2021-03-13 06:23:42 +00:00
|
|
|
|
var allFound = true;
|
2020-12-30 15:36:08 +00:00
|
|
|
|
len = val.generics.length;
|
2021-03-13 06:23:42 +00:00
|
|
|
|
for (x = 0; x < len; ++x) {
|
|
|
|
|
firstGeneric = getObjectNameFromId(val.generics[x]);
|
|
|
|
|
if (elems[firstGeneric]) {
|
|
|
|
|
elems[firstGeneric] -= 1;
|
|
|
|
|
} else {
|
|
|
|
|
allFound = false;
|
|
|
|
|
break;
|
2017-11-01 16:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (allFound === true) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2017-11-11 22:53:37 +00:00
|
|
|
|
// If the type has generics but don't match, then it won't return at this point.
|
|
|
|
|
// Otherwise, `checkGenerics` will return 0 and it'll return.
|
2018-06-16 18:44:55 +00:00
|
|
|
|
if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length !== 0) {
|
2017-11-21 23:17:30 +00:00
|
|
|
|
var tmp_lev = checkGenerics(obj, val);
|
|
|
|
|
if (tmp_lev <= MAX_LEV_DISTANCE) {
|
|
|
|
|
return tmp_lev;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
2017-11-01 16:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Names didn't match so let's check if one of the generic types could.
|
|
|
|
|
if (literalSearch === true) {
|
2018-06-16 18:44:55 +00:00
|
|
|
|
if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
|
2021-01-08 13:52:12 +00:00
|
|
|
|
return obj[GENERICS_DATA].some(
|
2020-12-30 15:36:08 +00:00
|
|
|
|
function(name) {
|
|
|
|
|
return name === val.name;
|
|
|
|
|
});
|
2017-11-01 16:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
lev_distance = Math.min(levenshtein(obj[NAME], val.name), lev_distance);
|
2017-11-21 23:17:30 +00:00
|
|
|
|
if (lev_distance <= MAX_LEV_DISTANCE) {
|
2019-03-07 14:33:18 +00:00
|
|
|
|
// The generics didn't match but the name kinda did so we give it
|
|
|
|
|
// a levenshtein distance value that isn't *this* good so it goes
|
|
|
|
|
// into the search results but not too high.
|
|
|
|
|
lev_distance = Math.ceil((checkGenerics(obj, val) + lev_distance) / 2);
|
2018-06-16 18:44:55 +00:00
|
|
|
|
} else if (obj.length > GENERICS_DATA && obj[GENERICS_DATA].length > 0) {
|
2017-11-21 23:17:30 +00:00
|
|
|
|
// We can check if the type we're looking for is inside the generics!
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var olength = obj[GENERICS_DATA].length;
|
|
|
|
|
for (x = 0; x < olength; ++x) {
|
2018-06-16 18:44:55 +00:00
|
|
|
|
lev_distance = Math.min(levenshtein(obj[GENERICS_DATA][x], val.name),
|
2017-11-17 20:59:06 +00:00
|
|
|
|
lev_distance);
|
2017-11-01 16:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-11 22:53:37 +00:00
|
|
|
|
// Now whatever happens, the returned distance is "less good" so we should mark it
|
|
|
|
|
// as such, and so we add 1 to the distance to make it "less good".
|
|
|
|
|
return lev_distance + 1;
|
2017-11-01 16:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-23 01:38:33 +00:00
|
|
|
|
function findArg(obj, val, literalSearch, typeFilter) {
|
2017-11-01 16:38:37 +00:00
|
|
|
|
var lev_distance = MAX_LEV_DISTANCE + 1;
|
|
|
|
|
|
2020-02-23 01:38:33 +00:00
|
|
|
|
if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var length = obj.type[INPUTS_DATA].length;
|
|
|
|
|
for (var i = 0; i < length; i++) {
|
2020-02-23 01:38:33 +00:00
|
|
|
|
var tmp = obj.type[INPUTS_DATA][i];
|
|
|
|
|
if (typePassesFilter(typeFilter, tmp[1]) === false) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-02-23 18:09:00 +00:00
|
|
|
|
tmp = checkType(tmp, val, literalSearch);
|
2020-02-23 01:38:33 +00:00
|
|
|
|
if (literalSearch === true) {
|
|
|
|
|
if (tmp === true) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
2017-10-29 12:39:11 +00:00
|
|
|
|
}
|
2017-11-17 20:59:06 +00:00
|
|
|
|
lev_distance = Math.min(tmp, lev_distance);
|
2017-10-29 17:22:13 +00:00
|
|
|
|
if (lev_distance === 0) {
|
|
|
|
|
return 0;
|
2017-10-03 22:06:07 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-01 16:38:37 +00:00
|
|
|
|
return literalSearch === true ? false : lev_distance;
|
2017-10-03 22:06:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-23 01:38:33 +00:00
|
|
|
|
function checkReturned(obj, val, literalSearch, typeFilter) {
|
2017-10-29 17:22:13 +00:00
|
|
|
|
var lev_distance = MAX_LEV_DISTANCE + 1;
|
2017-11-01 16:38:37 +00:00
|
|
|
|
|
2018-06-16 18:44:55 +00:00
|
|
|
|
if (obj && obj.type && obj.type.length > OUTPUT_DATA) {
|
2019-03-07 15:47:40 +00:00
|
|
|
|
var ret = obj.type[OUTPUT_DATA];
|
2020-02-23 01:38:33 +00:00
|
|
|
|
if (typeof ret[0] === "string") {
|
2019-03-07 15:47:40 +00:00
|
|
|
|
ret = [ret];
|
2017-10-29 12:39:11 +00:00
|
|
|
|
}
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var x = 0, len = ret.length; x < len; ++x) {
|
2020-02-23 18:09:00 +00:00
|
|
|
|
var tmp = ret[x];
|
|
|
|
|
if (typePassesFilter(typeFilter, tmp[1]) === false) {
|
2020-02-23 01:38:33 +00:00
|
|
|
|
continue;
|
2019-03-07 23:16:48 +00:00
|
|
|
|
}
|
2020-03-09 13:47:24 +00:00
|
|
|
|
tmp = checkType(tmp, val, literalSearch);
|
2019-03-07 23:16:48 +00:00
|
|
|
|
if (literalSearch === true) {
|
|
|
|
|
if (tmp === true) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
2019-03-07 15:47:40 +00:00
|
|
|
|
}
|
|
|
|
|
lev_distance = Math.min(tmp, lev_distance);
|
|
|
|
|
if (lev_distance === 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2017-10-29 17:22:13 +00:00
|
|
|
|
}
|
2017-10-29 12:39:11 +00:00
|
|
|
|
}
|
2017-11-01 16:38:37 +00:00
|
|
|
|
return literalSearch === true ? false : lev_distance;
|
2017-10-29 12:29:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-21 22:21:08 +00:00
|
|
|
|
function checkPath(contains, lastElem, ty) {
|
|
|
|
|
if (contains.length === 0) {
|
2017-12-12 23:20:45 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2017-11-19 12:41:56 +00:00
|
|
|
|
var ret_lev = MAX_LEV_DISTANCE + 1;
|
2017-11-18 16:30:19 +00:00
|
|
|
|
var path = ty.path.split("::");
|
2017-11-19 12:41:56 +00:00
|
|
|
|
|
|
|
|
|
if (ty.parent && ty.parent.name) {
|
|
|
|
|
path.push(ty.parent.name.toLowerCase());
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var length = path.length;
|
|
|
|
|
var clength = contains.length;
|
|
|
|
|
if (clength > length) {
|
2017-11-18 16:30:19 +00:00
|
|
|
|
return MAX_LEV_DISTANCE + 1;
|
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
for (var i = 0; i < length; ++i) {
|
|
|
|
|
if (i + clength > length) {
|
2017-11-19 12:41:56 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
var lev_total = 0;
|
|
|
|
|
var aborted = false;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
for (var x = 0; x < clength; ++x) {
|
2018-08-21 22:21:08 +00:00
|
|
|
|
var lev = levenshtein(path[i + x], contains[x]);
|
2017-11-19 12:41:56 +00:00
|
|
|
|
if (lev > MAX_LEV_DISTANCE) {
|
|
|
|
|
aborted = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
lev_total += lev;
|
|
|
|
|
}
|
|
|
|
|
if (aborted === false) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
ret_lev = Math.min(ret_lev, Math.round(lev_total / clength));
|
2017-11-18 16:30:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-19 12:41:56 +00:00
|
|
|
|
return ret_lev;
|
2017-11-18 16:30:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-08-04 15:40:23 +00:00
|
|
|
|
function typePassesFilter(filter, type) {
|
|
|
|
|
// No filter
|
2020-02-23 01:38:33 +00:00
|
|
|
|
if (filter <= NO_TYPE_FILTER) return true;
|
2015-08-04 15:40:23 +00:00
|
|
|
|
|
|
|
|
|
// Exact match
|
|
|
|
|
if (filter === type) return true;
|
|
|
|
|
|
|
|
|
|
// Match related items
|
|
|
|
|
var name = itemTypes[type];
|
|
|
|
|
switch (itemTypes[filter]) {
|
|
|
|
|
case "constant":
|
2020-02-23 01:38:33 +00:00
|
|
|
|
return name === "associatedconstant";
|
2015-08-04 15:40:23 +00:00
|
|
|
|
case "fn":
|
2020-02-23 01:38:33 +00:00
|
|
|
|
return name === "method" || name === "tymethod";
|
2015-08-04 15:40:23 +00:00
|
|
|
|
case "type":
|
2020-02-23 01:38:33 +00:00
|
|
|
|
return name === "primitive" || name === "associatedtype";
|
|
|
|
|
case "trait":
|
|
|
|
|
return name === "traitalias";
|
2015-08-04 15:40:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No match
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 12:51:06 +00:00
|
|
|
|
function createAliasFromItem(item) {
|
|
|
|
|
return {
|
|
|
|
|
crate: item.crate,
|
|
|
|
|
name: item.name,
|
|
|
|
|
path: item.path,
|
|
|
|
|
desc: item.desc,
|
|
|
|
|
ty: item.ty,
|
|
|
|
|
parent: item.parent,
|
2020-05-04 13:26:17 +00:00
|
|
|
|
type: item.type,
|
2020-05-04 12:51:06 +00:00
|
|
|
|
is_alias: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-30 18:53:40 +00:00
|
|
|
|
function handleAliases(ret, query, filterCrates) {
|
2020-05-07 19:42:41 +00:00
|
|
|
|
// We separate aliases and crate aliases because we want to have current crate
|
|
|
|
|
// aliases to be before the others in the displayed results.
|
2020-05-04 12:51:06 +00:00
|
|
|
|
var aliases = [];
|
2020-05-07 19:42:41 +00:00
|
|
|
|
var crateAliases = [];
|
2020-06-23 08:18:51 +00:00
|
|
|
|
if (filterCrates !== undefined) {
|
|
|
|
|
if (ALIASES[filterCrates] && ALIASES[filterCrates][query.search]) {
|
2020-12-30 15:36:08 +00:00
|
|
|
|
var query_aliases = ALIASES[filterCrates][query.search];
|
|
|
|
|
var len = query_aliases.length;
|
|
|
|
|
for (var i = 0; i < len; ++i) {
|
|
|
|
|
aliases.push(createAliasFromItem(searchIndex[query_aliases[i]]));
|
2020-06-23 08:18:51 +00:00
|
|
|
|
}
|
2020-04-30 18:53:40 +00:00
|
|
|
|
}
|
2020-05-04 12:51:06 +00:00
|
|
|
|
} else {
|
|
|
|
|
Object.keys(ALIASES).forEach(function(crate) {
|
|
|
|
|
if (ALIASES[crate][query.search]) {
|
2020-05-07 19:42:41 +00:00
|
|
|
|
var pushTo = crate === window.currentCrate ? crateAliases : aliases;
|
2020-12-30 15:36:08 +00:00
|
|
|
|
var query_aliases = ALIASES[crate][query.search];
|
|
|
|
|
var len = query_aliases.length;
|
|
|
|
|
for (var i = 0; i < len; ++i) {
|
|
|
|
|
pushTo.push(createAliasFromItem(searchIndex[query_aliases[i]]));
|
2020-05-04 12:51:06 +00:00
|
|
|
|
}
|
2020-04-30 18:53:40 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
2020-05-04 12:51:06 +00:00
|
|
|
|
}
|
2020-05-07 19:42:41 +00:00
|
|
|
|
|
|
|
|
|
var sortFunc = function(aaa, bbb) {
|
2020-05-04 12:51:06 +00:00
|
|
|
|
if (aaa.path < bbb.path) {
|
|
|
|
|
return 1;
|
|
|
|
|
} else if (aaa.path === bbb.path) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
2020-05-07 19:42:41 +00:00
|
|
|
|
};
|
|
|
|
|
crateAliases.sort(sortFunc);
|
|
|
|
|
aliases.sort(sortFunc);
|
2020-05-04 12:51:06 +00:00
|
|
|
|
|
2020-05-07 19:42:41 +00:00
|
|
|
|
var pushFunc = function(alias) {
|
2020-05-04 12:51:06 +00:00
|
|
|
|
alias.alias = query.raw;
|
|
|
|
|
var res = buildHrefAndPath(alias);
|
|
|
|
|
alias.displayPath = pathSplitter(res[0]);
|
|
|
|
|
alias.fullPath = alias.displayPath + alias.name;
|
|
|
|
|
alias.href = res[1];
|
|
|
|
|
|
|
|
|
|
ret.others.unshift(alias);
|
|
|
|
|
if (ret.others.length > MAX_RESULTS) {
|
|
|
|
|
ret.others.pop();
|
2020-04-30 18:53:40 +00:00
|
|
|
|
}
|
2020-05-07 19:42:41 +00:00
|
|
|
|
};
|
|
|
|
|
onEach(aliases, pushFunc);
|
|
|
|
|
onEach(crateAliases, pushFunc);
|
2020-04-30 18:53:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-09-19 05:18:38 +00:00
|
|
|
|
// quoted values mean literal search
|
2014-04-08 17:47:52 +00:00
|
|
|
|
var nSearchWords = searchWords.length;
|
2020-12-30 15:36:08 +00:00
|
|
|
|
var i, it;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var ty;
|
|
|
|
|
var fullId;
|
|
|
|
|
var returned;
|
|
|
|
|
var in_args;
|
2020-12-30 15:36:08 +00:00
|
|
|
|
var len;
|
2014-03-16 08:08:56 +00:00
|
|
|
|
if ((val.charAt(0) === "\"" || val.charAt(0) === "'") &&
|
|
|
|
|
val.charAt(val.length - 1) === val.charAt(0))
|
|
|
|
|
{
|
2017-11-01 16:38:37 +00:00
|
|
|
|
val = extractGenerics(val.substr(1, val.length - 2));
|
2018-11-16 15:31:07 +00:00
|
|
|
|
for (i = 0; i < nSearchWords; ++i) {
|
2018-09-30 22:47:54 +00:00
|
|
|
|
if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-02-23 01:38:33 +00:00
|
|
|
|
in_args = findArg(searchIndex[i], val, true, typeFilter);
|
|
|
|
|
returned = checkReturned(searchIndex[i], val, true, typeFilter);
|
2018-11-16 15:31:07 +00:00
|
|
|
|
ty = searchIndex[i];
|
2021-03-13 06:23:42 +00:00
|
|
|
|
fullId = ty.id;
|
2017-11-17 20:59:06 +00:00
|
|
|
|
|
2020-02-23 01:38:33 +00:00
|
|
|
|
if (searchWords[i] === val.name
|
|
|
|
|
&& typePassesFilter(typeFilter, searchIndex[i].ty)
|
|
|
|
|
&& results[fullId] === undefined) {
|
|
|
|
|
results[fullId] = {
|
|
|
|
|
id: i,
|
|
|
|
|
index: -1,
|
|
|
|
|
dontValidate: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (in_args === true && results_in_args[fullId] === undefined) {
|
|
|
|
|
results_in_args[fullId] = {
|
|
|
|
|
id: i,
|
|
|
|
|
index: -1,
|
|
|
|
|
dontValidate: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (returned === true && results_returned[fullId] === undefined) {
|
|
|
|
|
results_returned[fullId] = {
|
|
|
|
|
id: i,
|
|
|
|
|
index: -1,
|
|
|
|
|
dontValidate: true,
|
|
|
|
|
};
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-10-03 22:06:07 +00:00
|
|
|
|
query.inputs = [val];
|
|
|
|
|
query.output = val;
|
|
|
|
|
query.search = val;
|
2015-02-25 23:03:06 +00:00
|
|
|
|
// searching by type
|
|
|
|
|
} else if (val.search("->") > -1) {
|
2018-04-13 20:54:09 +00:00
|
|
|
|
var trimmer = function(s) { return s.trim(); };
|
2015-02-25 23:03:06 +00:00
|
|
|
|
var parts = val.split("->").map(trimmer);
|
|
|
|
|
var input = parts[0];
|
|
|
|
|
// sort inputs so that order does not matter
|
2017-10-03 22:06:07 +00:00
|
|
|
|
var inputs = input.split(",").map(trimmer).sort();
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (i = 0, len = inputs.length; i < len; ++i) {
|
2017-11-01 16:38:37 +00:00
|
|
|
|
inputs[i] = extractGenerics(inputs[i]);
|
|
|
|
|
}
|
|
|
|
|
var output = extractGenerics(parts[1]);
|
2015-02-25 23:03:06 +00:00
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
for (i = 0; i < nSearchWords; ++i) {
|
2018-09-30 22:47:54 +00:00
|
|
|
|
if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2015-02-25 23:03:06 +00:00
|
|
|
|
var type = searchIndex[i].type;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
ty = searchIndex[i];
|
2015-02-25 23:03:06 +00:00
|
|
|
|
if (!type) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2021-03-13 06:23:42 +00:00
|
|
|
|
fullId = ty.id;
|
2015-02-25 23:03:06 +00:00
|
|
|
|
|
2020-02-23 01:38:33 +00:00
|
|
|
|
returned = checkReturned(ty, output, true, NO_TYPE_FILTER);
|
2017-11-01 16:38:37 +00:00
|
|
|
|
if (output.name === "*" || returned === true) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
in_args = false;
|
2019-04-01 22:07:51 +00:00
|
|
|
|
var is_module = false;
|
2017-11-01 16:38:37 +00:00
|
|
|
|
|
2017-10-03 22:06:07 +00:00
|
|
|
|
if (input === "*") {
|
2019-04-01 22:07:51 +00:00
|
|
|
|
is_module = true;
|
2017-10-03 22:06:07 +00:00
|
|
|
|
} else {
|
|
|
|
|
var allFound = true;
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (it = 0, len = inputs.length; allFound === true && it < len; it++) {
|
2017-11-01 16:38:37 +00:00
|
|
|
|
allFound = checkType(type, inputs[it], true);
|
2017-10-03 22:06:07 +00:00
|
|
|
|
}
|
2017-11-12 12:19:15 +00:00
|
|
|
|
in_args = allFound;
|
2017-11-01 16:38:37 +00:00
|
|
|
|
}
|
2017-11-21 23:17:30 +00:00
|
|
|
|
if (in_args === true) {
|
|
|
|
|
results_in_args[fullId] = {
|
|
|
|
|
id: i,
|
|
|
|
|
index: -1,
|
|
|
|
|
dontValidate: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
if (returned === true) {
|
|
|
|
|
results_returned[fullId] = {
|
|
|
|
|
id: i,
|
|
|
|
|
index: -1,
|
|
|
|
|
dontValidate: true,
|
|
|
|
|
};
|
|
|
|
|
}
|
2019-04-01 22:07:51 +00:00
|
|
|
|
if (is_module === true) {
|
2017-11-21 23:17:30 +00:00
|
|
|
|
results[fullId] = {
|
|
|
|
|
id: i,
|
|
|
|
|
index: -1,
|
|
|
|
|
dontValidate: true,
|
|
|
|
|
};
|
2017-10-03 22:06:07 +00:00
|
|
|
|
}
|
2015-02-25 23:03:06 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-01 16:38:37 +00:00
|
|
|
|
query.inputs = inputs.map(function(input) {
|
|
|
|
|
return input.name;
|
|
|
|
|
});
|
|
|
|
|
query.output = output.name;
|
2013-09-19 05:18:38 +00:00
|
|
|
|
} else {
|
2017-10-03 22:06:07 +00:00
|
|
|
|
query.inputs = [val];
|
|
|
|
|
query.output = val;
|
|
|
|
|
query.search = val;
|
2013-09-19 05:18:38 +00:00
|
|
|
|
// gather matching search results up to a certain maximum
|
|
|
|
|
val = val.replace(/\_/g, "");
|
2017-11-18 16:30:19 +00:00
|
|
|
|
|
|
|
|
|
var valGenerics = extractGenerics(val);
|
|
|
|
|
|
|
|
|
|
var paths = valLower.split("::");
|
|
|
|
|
var j;
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (j = 0, len = paths.length; j < len; ++j) {
|
2017-11-18 16:30:19 +00:00
|
|
|
|
if (paths[j] === "") {
|
|
|
|
|
paths.splice(j, 1);
|
|
|
|
|
j -= 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
val = paths[paths.length - 1];
|
2018-08-21 22:21:08 +00:00
|
|
|
|
var contains = paths.slice(0, paths.length > 1 ? paths.length - 1 : 1);
|
2017-11-18 16:30:19 +00:00
|
|
|
|
|
2019-11-14 23:45:08 +00:00
|
|
|
|
var lev;
|
2017-11-18 16:30:19 +00:00
|
|
|
|
for (j = 0; j < nSearchWords; ++j) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
ty = searchIndex[j];
|
2018-09-30 22:47:54 +00:00
|
|
|
|
if (!ty || (filterCrates !== undefined && ty.crate !== filterCrates)) {
|
2017-11-18 16:30:19 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
var lev_add = 0;
|
|
|
|
|
if (paths.length > 1) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
lev = checkPath(contains, paths[paths.length - 1], ty);
|
2017-11-18 16:30:19 +00:00
|
|
|
|
if (lev > MAX_LEV_DISTANCE) {
|
2017-10-29 17:22:13 +00:00
|
|
|
|
continue;
|
2017-11-18 16:30:19 +00:00
|
|
|
|
} else if (lev > 0) {
|
2019-09-02 13:03:35 +00:00
|
|
|
|
lev_add = lev / 10;
|
2017-10-29 17:22:13 +00:00
|
|
|
|
}
|
2017-11-18 16:30:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
returned = MAX_LEV_DISTANCE + 1;
|
|
|
|
|
in_args = MAX_LEV_DISTANCE + 1;
|
2017-11-18 16:30:19 +00:00
|
|
|
|
var index = -1;
|
|
|
|
|
// we want lev results to go lower than others
|
2018-11-16 15:31:07 +00:00
|
|
|
|
lev = MAX_LEV_DISTANCE + 1;
|
2021-03-13 06:23:42 +00:00
|
|
|
|
fullId = ty.id;
|
2017-11-18 16:30:19 +00:00
|
|
|
|
|
2017-11-21 23:17:30 +00:00
|
|
|
|
if (searchWords[j].indexOf(split[i]) > -1 ||
|
|
|
|
|
searchWords[j].indexOf(val) > -1 ||
|
2021-03-14 21:43:10 +00:00
|
|
|
|
ty.normalizedName.indexOf(val) > -1)
|
2017-11-18 16:30:19 +00:00
|
|
|
|
{
|
|
|
|
|
// filter type: ... queries
|
2017-12-11 23:19:36 +00:00
|
|
|
|
if (typePassesFilter(typeFilter, ty.ty) && results[fullId] === undefined) {
|
2021-03-14 21:43:10 +00:00
|
|
|
|
index = ty.normalizedName.indexOf(val);
|
2017-11-01 16:38:37 +00:00
|
|
|
|
}
|
2017-11-18 16:30:19 +00:00
|
|
|
|
}
|
2017-11-21 23:17:30 +00:00
|
|
|
|
if ((lev = levenshtein(searchWords[j], val)) <= MAX_LEV_DISTANCE) {
|
2017-12-11 23:19:36 +00:00
|
|
|
|
if (typePassesFilter(typeFilter, ty.ty) === false) {
|
2017-11-21 23:17:30 +00:00
|
|
|
|
lev = MAX_LEV_DISTANCE + 1;
|
|
|
|
|
} else {
|
|
|
|
|
lev += 1;
|
2017-11-01 16:38:37 +00:00
|
|
|
|
}
|
2017-11-18 16:30:19 +00:00
|
|
|
|
}
|
2020-02-23 01:38:33 +00:00
|
|
|
|
in_args = findArg(ty, valGenerics, false, typeFilter);
|
|
|
|
|
returned = checkReturned(ty, valGenerics, false, typeFilter);
|
2017-11-21 23:17:30 +00:00
|
|
|
|
|
2017-11-18 16:30:19 +00:00
|
|
|
|
lev += lev_add;
|
2018-08-21 22:21:08 +00:00
|
|
|
|
if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) {
|
2017-12-15 14:42:38 +00:00
|
|
|
|
if (val.length < 6) {
|
|
|
|
|
lev -= 1;
|
|
|
|
|
} else {
|
|
|
|
|
lev = 0;
|
|
|
|
|
}
|
2017-12-12 23:20:45 +00:00
|
|
|
|
}
|
2017-11-21 23:17:30 +00:00
|
|
|
|
if (in_args <= MAX_LEV_DISTANCE) {
|
|
|
|
|
if (results_in_args[fullId] === undefined) {
|
|
|
|
|
results_in_args[fullId] = {
|
|
|
|
|
id: j,
|
|
|
|
|
index: index,
|
|
|
|
|
lev: in_args,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
results_in_args[fullId].lev =
|
|
|
|
|
Math.min(results_in_args[fullId].lev, in_args);
|
|
|
|
|
}
|
|
|
|
|
if (returned <= MAX_LEV_DISTANCE) {
|
|
|
|
|
if (results_returned[fullId] === undefined) {
|
|
|
|
|
results_returned[fullId] = {
|
|
|
|
|
id: j,
|
|
|
|
|
index: index,
|
|
|
|
|
lev: returned,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
results_returned[fullId].lev =
|
|
|
|
|
Math.min(results_returned[fullId].lev, returned);
|
|
|
|
|
}
|
|
|
|
|
if (index !== -1 || lev <= MAX_LEV_DISTANCE) {
|
2018-05-03 20:20:57 +00:00
|
|
|
|
if (index !== -1 && paths.length < 2) {
|
2017-11-21 23:17:30 +00:00
|
|
|
|
lev = 0;
|
|
|
|
|
}
|
2017-11-18 16:30:19 +00:00
|
|
|
|
if (results[fullId] === undefined) {
|
|
|
|
|
results[fullId] = {
|
|
|
|
|
id: j,
|
|
|
|
|
index: index,
|
|
|
|
|
lev: lev,
|
|
|
|
|
};
|
2014-01-10 04:59:53 +00:00
|
|
|
|
}
|
2017-11-21 23:17:30 +00:00
|
|
|
|
results[fullId].lev = Math.min(results[fullId].lev, lev);
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-01-10 04:59:53 +00:00
|
|
|
|
|
2018-04-19 16:23:12 +00:00
|
|
|
|
var ret = {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
"in_args": sortResults(results_in_args, true),
|
|
|
|
|
"returned": sortResults(results_returned, true),
|
|
|
|
|
"others": sortResults(results),
|
2017-11-21 23:17:30 +00:00
|
|
|
|
};
|
2020-04-30 18:53:40 +00:00
|
|
|
|
handleAliases(ret, query, filterCrates);
|
2018-04-19 16:23:12 +00:00
|
|
|
|
return ret;
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-01-10 04:59:53 +00:00
|
|
|
|
/**
|
2014-03-16 08:08:56 +00:00
|
|
|
|
* Validate performs the following boolean logic. For example:
|
|
|
|
|
* "File::open" will give IF A PARENT EXISTS => ("file" && "open")
|
|
|
|
|
* exists in (name || path || parent) OR => ("file" && "open") exists in
|
|
|
|
|
* (name || path )
|
|
|
|
|
*
|
|
|
|
|
* This could be written functionally, but I wanted to minimise
|
|
|
|
|
* functions on stack.
|
2014-01-10 04:59:53 +00:00
|
|
|
|
*
|
|
|
|
|
* @param {[string]} name [The name of the result]
|
|
|
|
|
* @param {[string]} path [The path of the result]
|
|
|
|
|
* @param {[string]} keys [The keys to be used (["file", "open"])]
|
|
|
|
|
* @param {[object]} parent [The parent of the result]
|
|
|
|
|
* @return {[boolean]} [Whether the result is valid or not]
|
|
|
|
|
*/
|
|
|
|
|
function validateResult(name, path, keys, parent) {
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var i = 0, len = keys.length; i < len; ++i) {
|
2014-07-03 21:07:16 +00:00
|
|
|
|
// each check is for validation so we negate the conditions and invalidate
|
2014-09-06 00:35:19 +00:00
|
|
|
|
if (!(
|
2014-07-03 21:07:16 +00:00
|
|
|
|
// check for an exact name match
|
2017-11-01 16:38:37 +00:00
|
|
|
|
name.indexOf(keys[i]) > -1 ||
|
2014-07-03 21:07:16 +00:00
|
|
|
|
// then an exact path match
|
2017-11-01 16:38:37 +00:00
|
|
|
|
path.indexOf(keys[i]) > -1 ||
|
2014-07-03 21:07:16 +00:00
|
|
|
|
// next if there is a parent, check for exact parent match
|
2019-11-27 23:02:37 +00:00
|
|
|
|
(parent !== undefined && parent.name !== undefined &&
|
2014-07-03 21:07:16 +00:00
|
|
|
|
parent.name.toLowerCase().indexOf(keys[i]) > -1) ||
|
|
|
|
|
// lastly check to see if the name was a levenshtein match
|
2017-11-01 16:38:37 +00:00
|
|
|
|
levenshtein(name, keys[i]) <= MAX_LEV_DISTANCE)) {
|
2014-07-03 21:07:16 +00:00
|
|
|
|
return false;
|
2014-01-10 04:59:53 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-07-03 21:07:16 +00:00
|
|
|
|
return true;
|
2014-01-10 04:59:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-07 15:19:44 +00:00
|
|
|
|
function getQuery(raw) {
|
|
|
|
|
var matches, type, query;
|
2014-08-09 13:38:10 +00:00
|
|
|
|
query = raw;
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2015-08-04 15:40:23 +00:00
|
|
|
|
matches = query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);
|
2013-09-19 05:18:38 +00:00
|
|
|
|
if (matches) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
type = matches[1].replace(/^const$/, "constant");
|
2013-09-19 05:18:38 +00:00
|
|
|
|
query = query.substring(matches[0].length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
2017-08-17 09:41:14 +00:00
|
|
|
|
raw: raw,
|
|
|
|
|
query: query,
|
|
|
|
|
type: type,
|
2015-05-22 12:14:28 +00:00
|
|
|
|
id: query + type
|
2013-09-19 05:18:38 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function initSearchNav() {
|
2017-04-14 14:37:09 +00:00
|
|
|
|
var hoverTimeout;
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2017-04-14 14:37:09 +00:00
|
|
|
|
var click_func = function(e) {
|
|
|
|
|
var el = e.target;
|
|
|
|
|
// to retrieve the real "owner" of the event.
|
2018-11-16 15:31:07 +00:00
|
|
|
|
while (el.tagName !== "TR") {
|
2017-04-14 14:37:09 +00:00
|
|
|
|
el = el.parentNode;
|
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var dst = e.target.getElementsByTagName("a");
|
2017-04-14 14:37:09 +00:00
|
|
|
|
if (dst.length < 1) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
dst = dst[0];
|
2015-05-22 12:14:28 +00:00
|
|
|
|
if (window.location.pathname === dst.pathname) {
|
2019-12-22 14:42:10 +00:00
|
|
|
|
hideSearchResults();
|
2014-08-31 21:11:42 +00:00
|
|
|
|
document.location.href = dst.href;
|
2013-09-27 18:06:07 +00:00
|
|
|
|
}
|
2017-04-14 14:37:09 +00:00
|
|
|
|
};
|
|
|
|
|
var mouseover_func = function(e) {
|
2020-06-02 02:18:38 +00:00
|
|
|
|
if (mouseMovedAfterSearch) {
|
|
|
|
|
var el = e.target;
|
|
|
|
|
// to retrieve the real "owner" of the event.
|
|
|
|
|
while (el.tagName !== "TR") {
|
|
|
|
|
el = el.parentNode;
|
|
|
|
|
}
|
|
|
|
|
clearTimeout(hoverTimeout);
|
|
|
|
|
hoverTimeout = setTimeout(function() {
|
|
|
|
|
onEachLazy(document.getElementsByClassName("search-results"), function(e) {
|
|
|
|
|
onEachLazy(e.getElementsByClassName("result"), function(i_e) {
|
|
|
|
|
removeClass(i_e, "highlighted");
|
|
|
|
|
});
|
2017-04-14 14:37:09 +00:00
|
|
|
|
});
|
2020-06-02 02:18:38 +00:00
|
|
|
|
addClass(el, "highlighted");
|
|
|
|
|
}, 20);
|
|
|
|
|
}
|
2017-04-14 14:37:09 +00:00
|
|
|
|
};
|
2018-12-02 00:22:44 +00:00
|
|
|
|
onEachLazy(document.getElementsByClassName("search-results"), function(e) {
|
|
|
|
|
onEachLazy(e.getElementsByClassName("result"), function(i_e) {
|
2017-04-14 14:37:09 +00:00
|
|
|
|
i_e.onclick = click_func;
|
|
|
|
|
i_e.onmouseover = mouseover_func;
|
|
|
|
|
});
|
2013-09-19 05:18:38 +00:00
|
|
|
|
});
|
|
|
|
|
|
2017-04-14 14:37:09 +00:00
|
|
|
|
search_input.onkeydown = function(e) {
|
2017-10-14 16:01:14 +00:00
|
|
|
|
// "actives" references the currently highlighted item in each search tab.
|
|
|
|
|
// Each array in "actives" represents a tab.
|
|
|
|
|
var actives = [[], [], []];
|
|
|
|
|
// "current" is used to know which tab we're looking into.
|
|
|
|
|
var current = 0;
|
2019-02-09 23:37:44 +00:00
|
|
|
|
onEachLazy(document.getElementById("results").childNodes, function(e) {
|
2020-08-28 11:30:21 +00:00
|
|
|
|
onEachLazy(e.getElementsByClassName("highlighted"), function(h_e) {
|
|
|
|
|
actives[current].push(h_e);
|
2017-04-14 14:37:09 +00:00
|
|
|
|
});
|
2017-10-14 16:01:14 +00:00
|
|
|
|
current += 1;
|
2017-04-14 14:37:09 +00:00
|
|
|
|
});
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2014-06-18 18:25:04 +00:00
|
|
|
|
if (e.which === 38) { // up
|
2020-12-09 19:47:55 +00:00
|
|
|
|
if (e.ctrlKey) { // Going through result tabs.
|
|
|
|
|
printTab(currentTab > 0 ? currentTab - 1 : 2);
|
|
|
|
|
} else {
|
|
|
|
|
if (!actives[currentTab].length ||
|
|
|
|
|
!actives[currentTab][0].previousElementSibling) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
addClass(actives[currentTab][0].previousElementSibling, "highlighted");
|
|
|
|
|
removeClass(actives[currentTab][0], "highlighted");
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
2020-06-02 02:21:39 +00:00
|
|
|
|
e.preventDefault();
|
2014-06-18 18:25:04 +00:00
|
|
|
|
} else if (e.which === 40) { // down
|
2020-12-09 19:47:55 +00:00
|
|
|
|
if (e.ctrlKey) { // Going through result tabs.
|
|
|
|
|
printTab(currentTab > 1 ? 0 : currentTab + 1);
|
|
|
|
|
} else if (!actives[currentTab].length) {
|
2019-02-09 23:37:44 +00:00
|
|
|
|
var results = document.getElementById("results").childNodes;
|
2017-04-14 14:37:09 +00:00
|
|
|
|
if (results.length > 0) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var res = results[currentTab].getElementsByClassName("result");
|
2017-04-14 14:37:09 +00:00
|
|
|
|
if (res.length > 0) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
addClass(res[0], "highlighted");
|
2017-04-14 14:37:09 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2017-10-14 16:01:14 +00:00
|
|
|
|
} else if (actives[currentTab][0].nextElementSibling) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
addClass(actives[currentTab][0].nextElementSibling, "highlighted");
|
|
|
|
|
removeClass(actives[currentTab][0], "highlighted");
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
2020-06-02 02:21:39 +00:00
|
|
|
|
e.preventDefault();
|
2014-06-18 18:25:04 +00:00
|
|
|
|
} else if (e.which === 13) { // return
|
2017-10-14 16:01:14 +00:00
|
|
|
|
if (actives[currentTab].length) {
|
|
|
|
|
document.location.href =
|
2018-11-16 15:31:07 +00:00
|
|
|
|
actives[currentTab][0].getElementsByTagName("a")[0].href;
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
2017-10-14 16:01:14 +00:00
|
|
|
|
} else if (e.which === 16) { // shift
|
|
|
|
|
// Does nothing, it's just to avoid losing "focus" on the highlighted element.
|
|
|
|
|
} else if (actives[currentTab].length > 0) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
removeClass(actives[currentTab][0], "highlighted");
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
2017-04-14 14:37:09 +00:00
|
|
|
|
};
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-04-25 17:50:32 +00:00
|
|
|
|
function buildHrefAndPath(item) {
|
|
|
|
|
var displayPath;
|
|
|
|
|
var href;
|
|
|
|
|
var type = itemTypes[item.ty];
|
|
|
|
|
var name = item.name;
|
2019-09-24 01:37:20 +00:00
|
|
|
|
var path = item.path;
|
2018-04-25 17:50:32 +00:00
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (type === "mod") {
|
2019-09-24 01:37:20 +00:00
|
|
|
|
displayPath = path + "::";
|
2021-01-18 11:03:53 +00:00
|
|
|
|
href = window.rootPath + path.replace(/::/g, "/") + "/" +
|
2018-11-16 15:31:07 +00:00
|
|
|
|
name + "/index.html";
|
2018-05-28 19:30:01 +00:00
|
|
|
|
} else if (type === "primitive" || type === "keyword") {
|
2018-04-25 17:50:32 +00:00
|
|
|
|
displayPath = "";
|
2021-01-18 11:03:53 +00:00
|
|
|
|
href = window.rootPath + path.replace(/::/g, "/") +
|
2018-11-16 15:31:07 +00:00
|
|
|
|
"/" + type + "." + name + ".html";
|
2018-04-25 17:50:32 +00:00
|
|
|
|
} else if (type === "externcrate") {
|
|
|
|
|
displayPath = "";
|
2021-01-18 11:03:53 +00:00
|
|
|
|
href = window.rootPath + name + "/index.html";
|
2018-04-25 17:50:32 +00:00
|
|
|
|
} else if (item.parent !== undefined) {
|
|
|
|
|
var myparent = item.parent;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var anchor = "#" + type + "." + name;
|
2018-04-25 17:50:32 +00:00
|
|
|
|
var parentType = itemTypes[myparent.ty];
|
2019-09-24 01:37:20 +00:00
|
|
|
|
var pageType = parentType;
|
|
|
|
|
var pageName = myparent.name;
|
|
|
|
|
|
2018-04-25 17:50:32 +00:00
|
|
|
|
if (parentType === "primitive") {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
displayPath = myparent.name + "::";
|
2019-09-24 01:37:20 +00:00
|
|
|
|
} else if (type === "structfield" && parentType === "variant") {
|
|
|
|
|
// Structfields belonging to variants are special: the
|
|
|
|
|
// final path element is the enum name.
|
2021-03-05 18:20:31 +00:00
|
|
|
|
var enumNameIdx = item.path.lastIndexOf("::");
|
|
|
|
|
var enumName = item.path.substr(enumNameIdx + 2);
|
|
|
|
|
path = item.path.substr(0, enumNameIdx);
|
2019-09-24 01:37:20 +00:00
|
|
|
|
displayPath = path + "::" + enumName + "::" + myparent.name + "::";
|
|
|
|
|
anchor = "#variant." + myparent.name + ".field." + name;
|
|
|
|
|
pageType = "enum";
|
|
|
|
|
pageName = enumName;
|
2018-04-25 17:50:32 +00:00
|
|
|
|
} else {
|
2019-09-24 01:37:20 +00:00
|
|
|
|
displayPath = path + "::" + myparent.name + "::";
|
2018-04-25 17:50:32 +00:00
|
|
|
|
}
|
2021-01-18 11:03:53 +00:00
|
|
|
|
href = window.rootPath + path.replace(/::/g, "/") +
|
2019-09-24 01:37:20 +00:00
|
|
|
|
"/" + pageType +
|
|
|
|
|
"." + pageName +
|
2018-11-16 15:31:07 +00:00
|
|
|
|
".html" + anchor;
|
2018-04-25 17:50:32 +00:00
|
|
|
|
} else {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
displayPath = item.path + "::";
|
2021-01-18 11:03:53 +00:00
|
|
|
|
href = window.rootPath + item.path.replace(/::/g, "/") +
|
2018-11-16 15:31:07 +00:00
|
|
|
|
"/" + type + "." + name + ".html";
|
2018-04-25 17:50:32 +00:00
|
|
|
|
}
|
|
|
|
|
return [displayPath, href];
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-25 22:36:00 +00:00
|
|
|
|
function escape(content) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var h1 = document.createElement("h1");
|
2018-04-25 22:36:00 +00:00
|
|
|
|
h1.textContent = content;
|
|
|
|
|
return h1.innerHTML;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function pathSplitter(path) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var tmp = "<span>" + path.replace(/::/g, "::</span><span>");
|
2018-05-05 14:36:49 +00:00
|
|
|
|
if (tmp.endsWith("<span>")) {
|
|
|
|
|
return tmp.slice(0, tmp.length - 6);
|
|
|
|
|
}
|
|
|
|
|
return tmp;
|
2018-04-25 22:36:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-03 22:06:07 +00:00
|
|
|
|
function addTab(array, query, display) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var extraStyle = "";
|
2017-10-03 22:06:07 +00:00
|
|
|
|
if (display === false) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
extraStyle = " style=\"display: none;\"";
|
2017-10-03 22:06:07 +00:00
|
|
|
|
}
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var output = "";
|
2018-04-25 22:36:00 +00:00
|
|
|
|
var duplicates = {};
|
2018-05-12 11:52:25 +00:00
|
|
|
|
var length = 0;
|
2017-10-03 22:06:07 +00:00
|
|
|
|
if (array.length > 0) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
output = "<table class=\"search-results\"" + extraStyle + ">";
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2017-10-03 22:06:07 +00:00
|
|
|
|
array.forEach(function(item) {
|
2018-04-25 22:36:00 +00:00
|
|
|
|
var name, type;
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
|
|
|
|
name = item.name;
|
2014-04-09 07:49:31 +00:00
|
|
|
|
type = itemTypes[item.ty];
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2018-04-25 22:36:00 +00:00
|
|
|
|
if (item.is_alias !== true) {
|
2018-05-12 21:44:40 +00:00
|
|
|
|
if (duplicates[item.fullPath]) {
|
2018-04-25 22:36:00 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2018-05-12 21:44:40 +00:00
|
|
|
|
duplicates[item.fullPath] = true;
|
2018-04-25 22:36:00 +00:00
|
|
|
|
}
|
2018-05-12 11:52:25 +00:00
|
|
|
|
length += 1;
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
output += "<tr class=\"" + type + " result\"><td>" +
|
|
|
|
|
"<a href=\"" + item.href + "\">" +
|
2018-04-25 22:36:00 +00:00
|
|
|
|
(item.is_alias === true ?
|
2018-11-16 15:31:07 +00:00
|
|
|
|
("<span class=\"alias\"><b>" + item.alias + " </b></span><span " +
|
|
|
|
|
"class=\"grey\"><i> - see </i></span>") : "") +
|
|
|
|
|
item.displayPath + "<span class=\"" + type + "\">" +
|
|
|
|
|
name + "</span></a></td><td>" +
|
|
|
|
|
"<a href=\"" + item.href + "\">" +
|
2020-10-05 03:42:34 +00:00
|
|
|
|
"<span class=\"desc\">" + item.desc +
|
2018-11-16 15:31:07 +00:00
|
|
|
|
" </span></a></td></tr>";
|
2013-09-19 05:18:38 +00:00
|
|
|
|
});
|
2018-11-16 15:31:07 +00:00
|
|
|
|
output += "</table>";
|
2013-09-19 05:18:38 +00:00
|
|
|
|
} else {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
output = "<div class=\"search-failed\"" + extraStyle + ">No results :(<br/>" +
|
|
|
|
|
"Try on <a href=\"https://duckduckgo.com/?q=" +
|
|
|
|
|
encodeURIComponent("rust " + query.query) +
|
|
|
|
|
"\">DuckDuckGo</a>?<br/><br/>" +
|
|
|
|
|
"Or try looking in one of these:<ul><li>The <a " +
|
|
|
|
|
"href=\"https://doc.rust-lang.org/reference/index.html\">Rust Reference</a> " +
|
|
|
|
|
" for technical details about the language.</li><li><a " +
|
|
|
|
|
"href=\"https://doc.rust-lang.org/rust-by-example/index.html\">Rust By " +
|
|
|
|
|
"Example</a> for expository code examples.</a></li><li>The <a " +
|
|
|
|
|
"href=\"https://doc.rust-lang.org/book/index.html\">Rust Book</a> for " +
|
|
|
|
|
"introductions to language features and the language itself.</li><li><a " +
|
|
|
|
|
"href=\"https://docs.rs\">Docs.rs</a> for documentation of crates released on" +
|
|
|
|
|
" <a href=\"https://crates.io/\">crates.io</a>.</li></ul></div>";
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
2018-05-12 11:52:25 +00:00
|
|
|
|
return [output, length];
|
2017-10-03 22:06:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-02 00:01:51 +00:00
|
|
|
|
function makeTabHeader(tabNb, text, nbElems) {
|
2017-10-14 14:31:48 +00:00
|
|
|
|
if (currentTab === tabNb) {
|
2020-12-10 10:38:12 +00:00
|
|
|
|
return "<button class=\"selected\">" + text +
|
|
|
|
|
" <div class=\"count\">(" + nbElems + ")</div></button>";
|
2017-10-14 14:31:48 +00:00
|
|
|
|
}
|
2020-12-10 10:38:12 +00:00
|
|
|
|
return "<button>" + text + " <div class=\"count\">(" + nbElems + ")</div></button>";
|
2017-10-14 14:31:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
function showResults(results) {
|
2020-08-22 14:49:56 +00:00
|
|
|
|
var search = getSearchElement();
|
|
|
|
|
if (results.others.length === 1
|
2020-09-23 21:14:43 +00:00
|
|
|
|
&& getSettingValue("go-to-only-result") === "true"
|
2020-08-24 10:59:16 +00:00
|
|
|
|
// By default, the search DOM element is "empty" (meaning it has no children not
|
|
|
|
|
// text content). Once a search has been run, it won't be empty, even if you press
|
|
|
|
|
// ESC or empty the search input (which also "cancels" the search).
|
2020-08-22 14:49:56 +00:00
|
|
|
|
&& (!search.firstChild || search.firstChild.innerText !== getSearchLoadingText()))
|
|
|
|
|
{
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var elem = document.createElement("a");
|
|
|
|
|
elem.href = results.others[0].href;
|
|
|
|
|
elem.style.display = "none";
|
2018-04-25 17:50:32 +00:00
|
|
|
|
// For firefox, we need the element to be in the DOM so it can be clicked.
|
|
|
|
|
document.body.appendChild(elem);
|
|
|
|
|
elem.click();
|
2020-08-22 14:49:56 +00:00
|
|
|
|
return;
|
2018-04-25 17:50:32 +00:00
|
|
|
|
}
|
2018-05-12 11:52:25 +00:00
|
|
|
|
var query = getQuery(search_input.value);
|
2017-10-03 22:06:07 +00:00
|
|
|
|
|
|
|
|
|
currentResults = query.id;
|
2018-05-12 11:52:25 +00:00
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var ret_others = addTab(results.others, query);
|
|
|
|
|
var ret_in_args = addTab(results.in_args, query, false);
|
|
|
|
|
var ret_returned = addTab(results.returned, query, false);
|
2018-05-12 11:52:25 +00:00
|
|
|
|
|
2020-12-26 14:57:27 +00:00
|
|
|
|
// Navigate to the relevant tab if the current tab is empty, like in case users search
|
|
|
|
|
// for "-> String". If they had selected another tab previously, they have to click on
|
|
|
|
|
// it again.
|
|
|
|
|
if ((currentTab === 0 && ret_others[1] === 0) ||
|
|
|
|
|
(currentTab === 1 && ret_in_args[1] === 0) ||
|
|
|
|
|
(currentTab === 2 && ret_returned[1] === 0)) {
|
|
|
|
|
if (ret_others[1] !== 0) {
|
|
|
|
|
currentTab = 0;
|
|
|
|
|
} else if (ret_in_args[1] !== 0) {
|
|
|
|
|
currentTab = 1;
|
|
|
|
|
} else if (ret_returned[1] !== 0) {
|
|
|
|
|
currentTab = 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var output = "<h1>Results for " + escape(query.query) +
|
|
|
|
|
(query.type ? " (type: " + escape(query.type) + ")" : "") + "</h1>" +
|
|
|
|
|
"<div id=\"titles\">" +
|
2018-05-12 11:52:25 +00:00
|
|
|
|
makeTabHeader(0, "In Names", ret_others[1]) +
|
|
|
|
|
makeTabHeader(1, "In Parameters", ret_in_args[1]) +
|
|
|
|
|
makeTabHeader(2, "In Return Types", ret_returned[1]) +
|
2018-11-16 15:31:07 +00:00
|
|
|
|
"</div><div id=\"results\">" +
|
|
|
|
|
ret_others[0] + ret_in_args[0] + ret_returned[0] + "</div>";
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
2017-04-14 14:37:09 +00:00
|
|
|
|
search.innerHTML = output;
|
2019-12-22 14:42:10 +00:00
|
|
|
|
showSearchResults(search);
|
2013-09-19 05:18:38 +00:00
|
|
|
|
initSearchNav();
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var elems = document.getElementById("titles").childNodes;
|
2017-10-03 22:06:07 +00:00
|
|
|
|
elems[0].onclick = function() { printTab(0); };
|
|
|
|
|
elems[1].onclick = function() { printTab(1); };
|
|
|
|
|
elems[2].onclick = function() { printTab(2); };
|
2017-10-29 12:21:18 +00:00
|
|
|
|
printTab(currentTab);
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-30 22:47:54 +00:00
|
|
|
|
function execSearch(query, searchWords, filterCrates) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
function getSmallest(arrays, positions, notDuplicates) {
|
|
|
|
|
var start = null;
|
|
|
|
|
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var it = 0, len = positions.length; it < len; ++it) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (arrays[it].length > positions[it] &&
|
|
|
|
|
(start === null || start > arrays[it][positions[it]].lev) &&
|
|
|
|
|
!notDuplicates[arrays[it][positions[it]].fullPath]) {
|
|
|
|
|
start = arrays[it][positions[it]].lev;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function mergeArrays(arrays) {
|
|
|
|
|
var ret = [];
|
|
|
|
|
var positions = [];
|
|
|
|
|
var notDuplicates = {};
|
|
|
|
|
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var x = 0, arrays_len = arrays.length; x < arrays_len; ++x) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
positions.push(0);
|
|
|
|
|
}
|
|
|
|
|
while (ret.length < MAX_RESULTS) {
|
|
|
|
|
var smallest = getSmallest(arrays, positions, notDuplicates);
|
|
|
|
|
|
|
|
|
|
if (smallest === null) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (x = 0; x < arrays_len && ret.length < MAX_RESULTS; ++x) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (arrays[x].length > positions[x] &&
|
|
|
|
|
arrays[x][positions[x]].lev === smallest &&
|
|
|
|
|
!notDuplicates[arrays[x][positions[x]].fullPath]) {
|
|
|
|
|
ret.push(arrays[x][positions[x]]);
|
|
|
|
|
notDuplicates[arrays[x][positions[x]].fullPath] = true;
|
|
|
|
|
positions[x] += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-14 15:01:28 +00:00
|
|
|
|
var queries = query.raw.split(",");
|
|
|
|
|
var results = {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
"in_args": [],
|
|
|
|
|
"returned": [],
|
|
|
|
|
"others": [],
|
2018-04-14 15:01:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var i = 0, len = queries.length; i < len; ++i) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
query = queries[i].trim();
|
2018-04-14 15:01:28 +00:00
|
|
|
|
if (query.length !== 0) {
|
2018-09-30 22:47:54 +00:00
|
|
|
|
var tmp = execQuery(getQuery(query), searchWords, filterCrates);
|
2018-04-14 15:01:28 +00:00
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
results.in_args.push(tmp.in_args);
|
|
|
|
|
results.returned.push(tmp.returned);
|
|
|
|
|
results.others.push(tmp.others);
|
2018-04-14 15:01:28 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (queries.length > 1) {
|
|
|
|
|
return {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
"in_args": mergeArrays(results.in_args),
|
|
|
|
|
"returned": mergeArrays(results.returned),
|
|
|
|
|
"others": mergeArrays(results.others),
|
2018-04-14 15:01:28 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
2020-04-30 18:53:40 +00:00
|
|
|
|
return {
|
|
|
|
|
"in_args": results.in_args[0],
|
|
|
|
|
"returned": results.returned[0],
|
|
|
|
|
"others": results.others[0],
|
|
|
|
|
};
|
2018-04-14 15:01:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-09-30 22:47:54 +00:00
|
|
|
|
function getFilterCrates() {
|
|
|
|
|
var elem = document.getElementById("crate-search");
|
|
|
|
|
|
2020-05-17 13:34:59 +00:00
|
|
|
|
if (elem && elem.value !== "All crates" && hasOwnProperty(rawSearchIndex, elem.value)) {
|
2018-09-30 22:47:54 +00:00
|
|
|
|
return elem.value;
|
|
|
|
|
}
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function search(e, forced) {
|
2014-01-23 01:44:27 +00:00
|
|
|
|
var params = getQueryStringParams();
|
2018-04-20 14:42:44 +00:00
|
|
|
|
var query = getQuery(search_input.value.trim());
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
|
|
|
|
if (e) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-30 22:47:54 +00:00
|
|
|
|
if (query.query.length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (forced !== true && query.id === currentResults) {
|
2018-04-20 14:42:44 +00:00
|
|
|
|
if (query.query.length > 0) {
|
|
|
|
|
putBackSearch(search_input);
|
|
|
|
|
}
|
2013-09-19 05:18:38 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-18 15:11:44 +00:00
|
|
|
|
// Update document title to maintain a meaningful browser history
|
2020-11-10 14:01:01 +00:00
|
|
|
|
searchTitle = "Results for " + query.query + " - Rust";
|
2015-06-18 15:11:44 +00:00
|
|
|
|
|
2014-03-16 08:08:56 +00:00
|
|
|
|
// Because searching is incremental by character, only the most
|
|
|
|
|
// recent search query is added to the browser history.
|
2014-01-23 01:44:27 +00:00
|
|
|
|
if (browserSupportsHistoryApi()) {
|
2021-01-25 12:21:12 +00:00
|
|
|
|
var newURL = getNakedUrl() + "?search=" + encodeURIComponent(query.raw) +
|
|
|
|
|
window.location.hash;
|
2014-01-23 01:44:27 +00:00
|
|
|
|
if (!history.state && !params.search) {
|
2021-01-25 12:21:12 +00:00
|
|
|
|
history.pushState(query, "", newURL);
|
2014-01-23 01:44:27 +00:00
|
|
|
|
} else {
|
2021-01-25 12:21:12 +00:00
|
|
|
|
history.replaceState(query, "", newURL);
|
2014-01-23 01:44:27 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-30 22:47:54 +00:00
|
|
|
|
var filterCrates = getFilterCrates();
|
2019-11-14 23:19:48 +00:00
|
|
|
|
showResults(execSearch(query, index, filterCrates));
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-16 08:08:56 +00:00
|
|
|
|
function buildIndex(rawSearchIndex) {
|
|
|
|
|
searchIndex = [];
|
|
|
|
|
var searchWords = [];
|
2021-03-15 18:58:34 +00:00
|
|
|
|
var i, word;
|
2020-05-04 12:51:06 +00:00
|
|
|
|
var currentIndex = 0;
|
2021-03-14 16:57:37 +00:00
|
|
|
|
var id = 0;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
|
2014-03-16 08:08:56 +00:00
|
|
|
|
for (var crate in rawSearchIndex) {
|
2020-05-17 13:34:59 +00:00
|
|
|
|
if (!hasOwnProperty(rawSearchIndex, crate)) { continue; }
|
2014-03-16 08:08:56 +00:00
|
|
|
|
|
2020-05-04 12:51:06 +00:00
|
|
|
|
var crateSize = 0;
|
|
|
|
|
|
2016-02-16 19:00:57 +00:00
|
|
|
|
searchWords.push(crate);
|
2021-03-14 21:43:10 +00:00
|
|
|
|
var normalizedName = crate.indexOf("_") === -1
|
2021-03-14 16:48:48 +00:00
|
|
|
|
? crate
|
|
|
|
|
: crate.replace(/_/g, "");
|
2021-03-13 17:12:17 +00:00
|
|
|
|
// This object should have exactly the same set of fields as the "row"
|
|
|
|
|
// object defined below. Your JavaScript runtime will thank you.
|
|
|
|
|
// https://mathiasbynens.be/notes/shapes-ics
|
2021-03-13 06:23:42 +00:00
|
|
|
|
var crateRow = {
|
2017-08-17 09:41:14 +00:00
|
|
|
|
crate: crate,
|
2016-02-16 19:00:57 +00:00
|
|
|
|
ty: 1, // == ExternCrate
|
|
|
|
|
name: crate,
|
|
|
|
|
path: "",
|
|
|
|
|
desc: rawSearchIndex[crate].doc,
|
2021-03-13 06:23:42 +00:00
|
|
|
|
parent: undefined,
|
2016-02-16 19:00:57 +00:00
|
|
|
|
type: null,
|
2021-03-14 16:57:37 +00:00
|
|
|
|
id: id,
|
2021-03-14 21:43:10 +00:00
|
|
|
|
normalizedName: normalizedName,
|
2021-03-13 06:23:42 +00:00
|
|
|
|
};
|
2021-03-14 16:57:37 +00:00
|
|
|
|
id += 1;
|
2021-03-13 06:23:42 +00:00
|
|
|
|
searchIndex.push(crateRow);
|
2020-05-04 12:51:06 +00:00
|
|
|
|
currentIndex += 1;
|
2016-02-16 19:00:57 +00:00
|
|
|
|
|
rustdoc: tweak the search index format
This essentially switches search-index.js from a "array of struct"
to a "struct of array" format, like this:
{
"doc": "Crate documentation",
"t": [ 1, 1, 2, 3, ... ],
"n": [ "Something", "SomethingElse", "whatever", "do_stuff", ... ],
"q": [ "a::b", "", "", "", ... ],
"d": [ "A Struct That Does Something", "Another Struct", "a function", "another function", ... ],
"i": [ 0, 0, 1, 1, ... ],
"f": [ null, null, [], [], ... ],
"p": ...,
"a": ...
}
So `{ty: 1, name: "Something", path: "a::b", desc: "A Struct That Does Something", parent_idx: 0, search_type: null}` is the first item.
This makes the uncompressed version smaller, but it really shows on the
compressed version:
notriddle:rust$ wc -c new-search-index1.52.0.js
2622427 new-search-index1.52.0.js
notriddle:rust$ wc -c old-search-index1.52.0.js
2725046 old-search-index1.52.0.js
notriddle:rust$ gzip new-search-index1.52.0.js
notriddle:rust$ gzip old-search-index1.52.0.js
notriddle:rust$ wc -c new-search-index1.52.0.js.gz
239385 new-search-index1.52.0.js.gz
notriddle:rust$ wc -c old-search-index1.52.0.js.gz
296328 old-search-index1.52.0.js.gz
notriddle:rust$
That's a 4% improvement on the uncompressed version (fewer `[]`),
and 20% improvement after gzipping it, thanks to putting like-typed
data next to each other. Any compression algorithm based on a sliding
window will probably show this kind of improvement.
2021-03-11 02:31:49 +00:00
|
|
|
|
// an array of (Number) item types
|
|
|
|
|
var itemTypes = rawSearchIndex[crate].t;
|
|
|
|
|
// an array of (String) item names
|
|
|
|
|
var itemNames = rawSearchIndex[crate].n;
|
|
|
|
|
// an array of (String) full paths (or empty string for previous path)
|
|
|
|
|
var itemPaths = rawSearchIndex[crate].q;
|
|
|
|
|
// an array of (String) descriptions
|
|
|
|
|
var itemDescs = rawSearchIndex[crate].d;
|
|
|
|
|
// an array of (Number) the parent path index + 1 to `paths`, or 0 if none
|
|
|
|
|
var itemParentIdxs = rawSearchIndex[crate].i;
|
|
|
|
|
// an array of (Object | null) the type of the function, if any
|
|
|
|
|
var itemFunctionSearchTypes = rawSearchIndex[crate].f;
|
2014-04-09 16:27:35 +00:00
|
|
|
|
// an array of [(Number) item type,
|
|
|
|
|
// (String) name]
|
2019-01-13 23:46:11 +00:00
|
|
|
|
var paths = rawSearchIndex[crate].p;
|
2020-05-04 12:51:06 +00:00
|
|
|
|
// a array of [(String) alias name
|
|
|
|
|
// [Number] index to items]
|
|
|
|
|
var aliases = rawSearchIndex[crate].a;
|
2014-04-09 16:27:35 +00:00
|
|
|
|
|
2019-09-24 01:37:20 +00:00
|
|
|
|
// convert `rawPaths` entries into object form
|
2014-04-09 16:27:35 +00:00
|
|
|
|
var len = paths.length;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
for (i = 0; i < len; ++i) {
|
2014-04-09 16:27:35 +00:00
|
|
|
|
paths[i] = {ty: paths[i][0], name: paths[i][1]};
|
|
|
|
|
}
|
|
|
|
|
|
rustdoc: tweak the search index format
This essentially switches search-index.js from a "array of struct"
to a "struct of array" format, like this:
{
"doc": "Crate documentation",
"t": [ 1, 1, 2, 3, ... ],
"n": [ "Something", "SomethingElse", "whatever", "do_stuff", ... ],
"q": [ "a::b", "", "", "", ... ],
"d": [ "A Struct That Does Something", "Another Struct", "a function", "another function", ... ],
"i": [ 0, 0, 1, 1, ... ],
"f": [ null, null, [], [], ... ],
"p": ...,
"a": ...
}
So `{ty: 1, name: "Something", path: "a::b", desc: "A Struct That Does Something", parent_idx: 0, search_type: null}` is the first item.
This makes the uncompressed version smaller, but it really shows on the
compressed version:
notriddle:rust$ wc -c new-search-index1.52.0.js
2622427 new-search-index1.52.0.js
notriddle:rust$ wc -c old-search-index1.52.0.js
2725046 old-search-index1.52.0.js
notriddle:rust$ gzip new-search-index1.52.0.js
notriddle:rust$ gzip old-search-index1.52.0.js
notriddle:rust$ wc -c new-search-index1.52.0.js.gz
239385 new-search-index1.52.0.js.gz
notriddle:rust$ wc -c old-search-index1.52.0.js.gz
296328 old-search-index1.52.0.js.gz
notriddle:rust$
That's a 4% improvement on the uncompressed version (fewer `[]`),
and 20% improvement after gzipping it, thanks to putting like-typed
data next to each other. Any compression algorithm based on a sliding
window will probably show this kind of improvement.
2021-03-11 02:31:49 +00:00
|
|
|
|
// convert `item*` into an object form, and construct word indices.
|
2014-04-09 16:27:35 +00:00
|
|
|
|
//
|
2014-03-16 08:08:56 +00:00
|
|
|
|
// before any analysis is performed lets gather the search terms to
|
|
|
|
|
// search against apart from the rest of the data. This is a quick
|
|
|
|
|
// operation that is cached for the life of the page state so that
|
|
|
|
|
// all other search operations have access to this cached data for
|
|
|
|
|
// faster analysis operations
|
rustdoc: tweak the search index format
This essentially switches search-index.js from a "array of struct"
to a "struct of array" format, like this:
{
"doc": "Crate documentation",
"t": [ 1, 1, 2, 3, ... ],
"n": [ "Something", "SomethingElse", "whatever", "do_stuff", ... ],
"q": [ "a::b", "", "", "", ... ],
"d": [ "A Struct That Does Something", "Another Struct", "a function", "another function", ... ],
"i": [ 0, 0, 1, 1, ... ],
"f": [ null, null, [], [], ... ],
"p": ...,
"a": ...
}
So `{ty: 1, name: "Something", path: "a::b", desc: "A Struct That Does Something", parent_idx: 0, search_type: null}` is the first item.
This makes the uncompressed version smaller, but it really shows on the
compressed version:
notriddle:rust$ wc -c new-search-index1.52.0.js
2622427 new-search-index1.52.0.js
notriddle:rust$ wc -c old-search-index1.52.0.js
2725046 old-search-index1.52.0.js
notriddle:rust$ gzip new-search-index1.52.0.js
notriddle:rust$ gzip old-search-index1.52.0.js
notriddle:rust$ wc -c new-search-index1.52.0.js.gz
239385 new-search-index1.52.0.js.gz
notriddle:rust$ wc -c old-search-index1.52.0.js.gz
296328 old-search-index1.52.0.js.gz
notriddle:rust$
That's a 4% improvement on the uncompressed version (fewer `[]`),
and 20% improvement after gzipping it, thanks to putting like-typed
data next to each other. Any compression algorithm based on a sliding
window will probably show this kind of improvement.
2021-03-11 02:31:49 +00:00
|
|
|
|
len = itemTypes.length;
|
2014-04-09 17:24:00 +00:00
|
|
|
|
var lastPath = "";
|
2018-11-16 15:31:07 +00:00
|
|
|
|
for (i = 0; i < len; ++i) {
|
2021-03-13 17:29:21 +00:00
|
|
|
|
// This object should have exactly the same set of fields as the "crateRow"
|
|
|
|
|
// object defined above.
|
2021-03-14 21:43:10 +00:00
|
|
|
|
if (typeof itemNames[i] === "string") {
|
2021-03-15 18:58:34 +00:00
|
|
|
|
word = itemNames[i].toLowerCase();
|
2021-03-14 21:43:10 +00:00
|
|
|
|
searchWords.push(word);
|
|
|
|
|
} else {
|
2021-03-15 18:58:34 +00:00
|
|
|
|
word = "";
|
2021-03-14 21:43:10 +00:00
|
|
|
|
searchWords.push("");
|
|
|
|
|
}
|
|
|
|
|
var normalizedName = word.indexOf("_") === -1
|
|
|
|
|
? word
|
|
|
|
|
: word.replace(/_/g, "");
|
2020-05-04 12:51:06 +00:00
|
|
|
|
var row = {
|
|
|
|
|
crate: crate,
|
rustdoc: tweak the search index format
This essentially switches search-index.js from a "array of struct"
to a "struct of array" format, like this:
{
"doc": "Crate documentation",
"t": [ 1, 1, 2, 3, ... ],
"n": [ "Something", "SomethingElse", "whatever", "do_stuff", ... ],
"q": [ "a::b", "", "", "", ... ],
"d": [ "A Struct That Does Something", "Another Struct", "a function", "another function", ... ],
"i": [ 0, 0, 1, 1, ... ],
"f": [ null, null, [], [], ... ],
"p": ...,
"a": ...
}
So `{ty: 1, name: "Something", path: "a::b", desc: "A Struct That Does Something", parent_idx: 0, search_type: null}` is the first item.
This makes the uncompressed version smaller, but it really shows on the
compressed version:
notriddle:rust$ wc -c new-search-index1.52.0.js
2622427 new-search-index1.52.0.js
notriddle:rust$ wc -c old-search-index1.52.0.js
2725046 old-search-index1.52.0.js
notriddle:rust$ gzip new-search-index1.52.0.js
notriddle:rust$ gzip old-search-index1.52.0.js
notriddle:rust$ wc -c new-search-index1.52.0.js.gz
239385 new-search-index1.52.0.js.gz
notriddle:rust$ wc -c old-search-index1.52.0.js.gz
296328 old-search-index1.52.0.js.gz
notriddle:rust$
That's a 4% improvement on the uncompressed version (fewer `[]`),
and 20% improvement after gzipping it, thanks to putting like-typed
data next to each other. Any compression algorithm based on a sliding
window will probably show this kind of improvement.
2021-03-11 02:31:49 +00:00
|
|
|
|
ty: itemTypes[i],
|
|
|
|
|
name: itemNames[i],
|
|
|
|
|
path: itemPaths[i] ? itemPaths[i] : lastPath,
|
|
|
|
|
desc: itemDescs[i],
|
|
|
|
|
parent: itemParentIdxs[i] > 0 ? paths[itemParentIdxs[i] - 1] : undefined,
|
|
|
|
|
type: itemFunctionSearchTypes[i],
|
2021-03-14 16:57:37 +00:00
|
|
|
|
id: id,
|
2021-03-14 21:43:10 +00:00
|
|
|
|
normalizedName: normalizedName,
|
2020-05-04 12:51:06 +00:00
|
|
|
|
};
|
2021-03-14 16:57:37 +00:00
|
|
|
|
id += 1;
|
2014-04-09 08:16:09 +00:00
|
|
|
|
searchIndex.push(row);
|
2014-04-09 17:24:00 +00:00
|
|
|
|
lastPath = row.path;
|
2020-05-04 12:51:06 +00:00
|
|
|
|
crateSize += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (aliases) {
|
|
|
|
|
ALIASES[crate] = {};
|
|
|
|
|
var j, local_aliases;
|
2020-05-13 15:03:37 +00:00
|
|
|
|
for (var alias_name in aliases) {
|
|
|
|
|
if (!aliases.hasOwnProperty(alias_name)) { continue; }
|
|
|
|
|
|
2020-05-04 12:51:06 +00:00
|
|
|
|
if (!ALIASES[crate].hasOwnProperty(alias_name)) {
|
|
|
|
|
ALIASES[crate][alias_name] = [];
|
|
|
|
|
}
|
2020-05-13 15:03:37 +00:00
|
|
|
|
local_aliases = aliases[alias_name];
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (j = 0, len = local_aliases.length; j < len; ++j) {
|
2020-05-04 12:51:06 +00:00
|
|
|
|
ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
2020-05-04 12:51:06 +00:00
|
|
|
|
currentIndex += crateSize;
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
|
|
|
|
return searchWords;
|
|
|
|
|
}
|
|
|
|
|
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
function registerSearchEvents() {
|
|
|
|
|
var searchAfter500ms = function() {
|
2020-05-31 12:27:33 +00:00
|
|
|
|
clearInputTimeout();
|
2017-04-14 14:37:09 +00:00
|
|
|
|
if (search_input.value.length === 0) {
|
2016-03-17 15:49:15 +00:00
|
|
|
|
if (browserSupportsHistoryApi()) {
|
2021-01-25 11:54:25 +00:00
|
|
|
|
history.replaceState("", window.currentCrate + " - Rust",
|
2021-01-25 12:21:12 +00:00
|
|
|
|
getNakedUrl() + window.location.hash);
|
2016-03-17 15:49:15 +00:00
|
|
|
|
}
|
2019-12-22 14:42:10 +00:00
|
|
|
|
hideSearchResults();
|
2015-09-29 20:47:01 +00:00
|
|
|
|
} else {
|
|
|
|
|
searchTimeout = setTimeout(search, 500);
|
2015-10-01 18:30:35 +00:00
|
|
|
|
}
|
2017-04-14 14:37:09 +00:00
|
|
|
|
};
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
search_input.onkeyup = searchAfter500ms;
|
|
|
|
|
search_input.oninput = searchAfter500ms;
|
2017-11-01 16:38:37 +00:00
|
|
|
|
document.getElementsByClassName("search-form")[0].onsubmit = function(e) {
|
2015-09-29 20:47:01 +00:00
|
|
|
|
e.preventDefault();
|
2020-05-31 12:27:33 +00:00
|
|
|
|
clearInputTimeout();
|
2015-09-29 20:47:01 +00:00
|
|
|
|
search();
|
2017-04-14 14:37:09 +00:00
|
|
|
|
};
|
|
|
|
|
search_input.onchange = function(e) {
|
2019-12-22 14:42:29 +00:00
|
|
|
|
if (e.target !== document.activeElement) {
|
|
|
|
|
// To prevent doing anything when it's from a blur event.
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-09-29 20:47:01 +00:00
|
|
|
|
// Do NOT e.preventDefault() here. It will prevent pasting.
|
2020-05-31 12:27:33 +00:00
|
|
|
|
clearInputTimeout();
|
2015-09-29 20:47:01 +00:00
|
|
|
|
// zero-timeout necessary here because at the time of event handler execution the
|
|
|
|
|
// pasted content is not in the input field yet. Shouldn’t make any difference for
|
|
|
|
|
// change, though.
|
|
|
|
|
setTimeout(search, 0);
|
2017-04-14 14:37:09 +00:00
|
|
|
|
};
|
|
|
|
|
search_input.onpaste = search_input.onchange;
|
2014-03-16 08:08:56 +00:00
|
|
|
|
|
2019-07-24 15:50:48 +00:00
|
|
|
|
var selectCrate = document.getElementById("crate-search");
|
2018-09-30 22:47:54 +00:00
|
|
|
|
if (selectCrate) {
|
|
|
|
|
selectCrate.onchange = function() {
|
2019-07-24 15:50:48 +00:00
|
|
|
|
updateLocalStorage("rustdoc-saved-filter-crate", selectCrate.value);
|
2018-09-30 22:47:54 +00:00
|
|
|
|
search(undefined, true);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-16 08:08:56 +00:00
|
|
|
|
// Push and pop states are used to add search results to the browser
|
|
|
|
|
// history.
|
2014-01-23 01:44:27 +00:00
|
|
|
|
if (browserSupportsHistoryApi()) {
|
2015-07-02 03:28:54 +00:00
|
|
|
|
// Store the previous <title> so we can revert back to it later.
|
2017-04-14 14:37:09 +00:00
|
|
|
|
var previousTitle = document.title;
|
2015-07-02 03:28:54 +00:00
|
|
|
|
|
2019-12-22 14:42:10 +00:00
|
|
|
|
window.addEventListener("popstate", function(e) {
|
2014-01-23 01:44:27 +00:00
|
|
|
|
var params = getQueryStringParams();
|
2015-07-02 03:28:54 +00:00
|
|
|
|
// Revert to the previous title manually since the History
|
|
|
|
|
// API ignores the title parameter.
|
2017-04-14 14:37:09 +00:00
|
|
|
|
document.title = previousTitle;
|
2014-03-16 08:08:56 +00:00
|
|
|
|
// When browsing forward to search results the previous
|
|
|
|
|
// search will be repeated, so the currentResults are
|
|
|
|
|
// cleared to ensure the search is successful.
|
2014-01-23 01:44:27 +00:00
|
|
|
|
currentResults = null;
|
2014-02-21 07:15:08 +00:00
|
|
|
|
// Synchronize search bar with query string state and
|
2014-04-28 20:52:54 +00:00
|
|
|
|
// perform the search. This will empty the bar if there's
|
|
|
|
|
// nothing there, which lets you really go back to a
|
|
|
|
|
// previous state with nothing in the bar.
|
2019-12-22 14:42:10 +00:00
|
|
|
|
if (params.search && params.search.length > 0) {
|
2018-04-24 18:23:57 +00:00
|
|
|
|
search_input.value = params.search;
|
2019-12-22 14:42:10 +00:00
|
|
|
|
// Some browsers fire "onpopstate" for every page load
|
|
|
|
|
// (Chrome), while others fire the event only when actually
|
|
|
|
|
// popping a state (Firefox), which is why search() is
|
|
|
|
|
// called both here and at the end of the startSearch()
|
|
|
|
|
// function.
|
|
|
|
|
search(e);
|
2017-05-12 13:31:43 +00:00
|
|
|
|
} else {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
search_input.value = "";
|
2019-12-22 14:42:10 +00:00
|
|
|
|
// When browsing back from search results the main page
|
|
|
|
|
// visibility must be reset.
|
|
|
|
|
hideSearchResults();
|
2017-05-12 13:31:43 +00:00
|
|
|
|
}
|
2019-12-22 14:42:10 +00:00
|
|
|
|
});
|
2014-01-23 01:44:27 +00:00
|
|
|
|
}
|
2021-02-25 03:31:07 +00:00
|
|
|
|
|
|
|
|
|
// This is required in firefox to avoid this problem: Navigating to a search result
|
|
|
|
|
// with the keyboard, hitting enter, and then hitting back would take you back to
|
|
|
|
|
// the doc page, rather than the search that should overlay it.
|
|
|
|
|
// This was an interaction between the back-forward cache and our handlers
|
|
|
|
|
// that try to sync state between the URL and the search input. To work around it,
|
|
|
|
|
// do a small amount of re-init on page show.
|
|
|
|
|
window.onpageshow = function(){
|
|
|
|
|
var qSearch = getQueryStringParams().search;
|
|
|
|
|
if (search_input.value === "" && qSearch) {
|
|
|
|
|
search_input.value = qSearch;
|
|
|
|
|
}
|
|
|
|
|
search();
|
|
|
|
|
};
|
2013-09-19 05:18:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-16 08:08:56 +00:00
|
|
|
|
index = buildIndex(rawSearchIndex);
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
registerSearchEvents();
|
|
|
|
|
// If there's a search term in the URL, execute the search now.
|
|
|
|
|
if (getQueryStringParams().search) {
|
|
|
|
|
search();
|
|
|
|
|
}
|
|
|
|
|
};
|
2013-09-19 05:18:38 +00:00
|
|
|
|
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
function addSidebarCrates(crates) {
|
2014-03-16 08:08:56 +00:00
|
|
|
|
// Draw a convenient sidebar of known crates if we have a listing
|
2021-01-18 11:03:53 +00:00
|
|
|
|
if (window.rootPath === "../" || window.rootPath === "./") {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var sidebar = document.getElementsByClassName("sidebar-elems")[0];
|
2018-03-05 21:40:43 +00:00
|
|
|
|
if (sidebar) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var div = document.createElement("div");
|
|
|
|
|
div.className = "block crate";
|
|
|
|
|
div.innerHTML = "<h3>Crates</h3>";
|
|
|
|
|
var ul = document.createElement("ul");
|
2018-03-05 21:40:43 +00:00
|
|
|
|
div.appendChild(ul);
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < crates.length; ++i) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var klass = "crate";
|
2021-01-18 11:03:53 +00:00
|
|
|
|
if (window.rootPath !== "./" && crates[i] === window.currentCrate) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
klass += " current";
|
2018-03-05 21:40:43 +00:00
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var link = document.createElement("a");
|
2021-01-18 11:03:53 +00:00
|
|
|
|
link.href = window.rootPath + crates[i] + "/index.html";
|
2018-03-05 21:40:43 +00:00
|
|
|
|
link.className = klass;
|
|
|
|
|
link.textContent = crates[i];
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var li = document.createElement("li");
|
2018-03-05 21:40:43 +00:00
|
|
|
|
li.appendChild(link);
|
|
|
|
|
ul.appendChild(li);
|
2014-03-16 08:08:56 +00:00
|
|
|
|
}
|
2018-03-05 21:40:43 +00:00
|
|
|
|
sidebar.appendChild(div);
|
2014-03-16 08:08:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
}
|
2014-03-04 19:24:20 +00:00
|
|
|
|
|
2015-03-05 07:35:43 +00:00
|
|
|
|
// delayed sidebar rendering.
|
2020-05-17 12:57:19 +00:00
|
|
|
|
window.initSidebarItems = function(items) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var sidebar = document.getElementsByClassName("sidebar-elems")[0];
|
2015-03-05 07:35:43 +00:00
|
|
|
|
var current = window.sidebarCurrent;
|
|
|
|
|
|
|
|
|
|
function block(shortty, longty) {
|
|
|
|
|
var filtered = items[shortty];
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (!filtered) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2015-03-05 07:35:43 +00:00
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var div = document.createElement("div");
|
|
|
|
|
div.className = "block " + shortty;
|
|
|
|
|
var h3 = document.createElement("h3");
|
2017-04-14 14:37:09 +00:00
|
|
|
|
h3.textContent = longty;
|
|
|
|
|
div.appendChild(h3);
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var ul = document.createElement("ul");
|
2015-03-05 07:35:43 +00:00
|
|
|
|
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var i = 0, len = filtered.length; i < len; ++i) {
|
2015-03-05 07:35:43 +00:00
|
|
|
|
var item = filtered[i];
|
|
|
|
|
var name = item[0];
|
|
|
|
|
var desc = item[1]; // can be null
|
|
|
|
|
|
|
|
|
|
var klass = shortty;
|
2015-05-22 12:14:28 +00:00
|
|
|
|
if (name === current.name && shortty === current.ty) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
klass += " current";
|
2015-03-05 07:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
var path;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (shortty === "mod") {
|
|
|
|
|
path = name + "/index.html";
|
2015-03-05 07:35:43 +00:00
|
|
|
|
} else {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
path = shortty + "." + name + ".html";
|
2015-03-05 07:35:43 +00:00
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var link = document.createElement("a");
|
2017-04-14 14:37:09 +00:00
|
|
|
|
link.href = current.relpath + path;
|
|
|
|
|
link.title = desc;
|
|
|
|
|
link.className = klass;
|
|
|
|
|
link.textContent = name;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var li = document.createElement("li");
|
2017-04-14 14:37:09 +00:00
|
|
|
|
li.appendChild(link);
|
|
|
|
|
ul.appendChild(li);
|
2015-03-05 07:35:43 +00:00
|
|
|
|
}
|
2017-04-14 14:37:09 +00:00
|
|
|
|
div.appendChild(ul);
|
2018-01-20 20:12:00 +00:00
|
|
|
|
if (sidebar) {
|
|
|
|
|
sidebar.appendChild(div);
|
|
|
|
|
}
|
2015-03-05 07:35:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-06-19 22:19:57 +00:00
|
|
|
|
block("primitive", "Primitive Types");
|
2015-03-05 07:35:43 +00:00
|
|
|
|
block("mod", "Modules");
|
2016-06-19 22:19:57 +00:00
|
|
|
|
block("macro", "Macros");
|
2015-03-05 07:35:43 +00:00
|
|
|
|
block("struct", "Structs");
|
|
|
|
|
block("enum", "Enums");
|
2017-07-24 00:18:58 +00:00
|
|
|
|
block("union", "Unions");
|
2016-06-19 22:19:57 +00:00
|
|
|
|
block("constant", "Constants");
|
|
|
|
|
block("static", "Statics");
|
2015-03-05 07:35:43 +00:00
|
|
|
|
block("trait", "Traits");
|
|
|
|
|
block("fn", "Functions");
|
2016-06-19 22:19:57 +00:00
|
|
|
|
block("type", "Type Definitions");
|
2017-11-15 09:31:23 +00:00
|
|
|
|
block("foreigntype", "Foreign Types");
|
2018-05-28 19:30:01 +00:00
|
|
|
|
block("keyword", "Keywords");
|
2019-02-07 00:02:23 +00:00
|
|
|
|
block("traitalias", "Trait Aliases");
|
2020-05-17 12:57:19 +00:00
|
|
|
|
};
|
2015-03-05 07:35:43 +00:00
|
|
|
|
|
2014-05-21 23:41:58 +00:00
|
|
|
|
window.register_implementors = function(imp) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var implementors = document.getElementById("implementors-list");
|
|
|
|
|
var synthetic_implementors = document.getElementById("synthetic-implementors-list");
|
2018-02-15 23:45:52 +00:00
|
|
|
|
|
2020-01-28 12:48:08 +00:00
|
|
|
|
if (synthetic_implementors) {
|
|
|
|
|
// This `inlined_types` variable is used to avoid having the same implementation
|
|
|
|
|
// showing up twice. For example "String" in the "Sync" doc page.
|
|
|
|
|
//
|
|
|
|
|
// By the way, this is only used by and useful for traits implemented automatically
|
|
|
|
|
// (like "Send" and "Sync").
|
|
|
|
|
var inlined_types = new Set();
|
|
|
|
|
onEachLazy(synthetic_implementors.getElementsByClassName("impl"), function(el) {
|
|
|
|
|
var aliases = el.getAttribute("aliases");
|
|
|
|
|
if (!aliases) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
aliases.split(",").forEach(function(alias) {
|
|
|
|
|
inlined_types.add(alias);
|
|
|
|
|
});
|
2020-01-13 22:28:34 +00:00
|
|
|
|
});
|
2020-01-28 12:48:08 +00:00
|
|
|
|
}
|
2020-01-13 22:28:34 +00:00
|
|
|
|
|
2014-05-21 23:41:58 +00:00
|
|
|
|
var libs = Object.getOwnPropertyNames(imp);
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var i = 0, llength = libs.length; i < llength; ++i) {
|
2021-01-18 11:03:53 +00:00
|
|
|
|
if (libs[i] === window.currentCrate) { continue; }
|
2014-05-28 00:52:40 +00:00
|
|
|
|
var structs = imp[libs[i]];
|
2018-02-10 19:34:46 +00:00
|
|
|
|
|
|
|
|
|
struct_loop:
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var j = 0, slength = structs.length; j < slength; ++j) {
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 21:16:55 +00:00
|
|
|
|
var struct = structs[j];
|
2018-02-15 23:45:52 +00:00
|
|
|
|
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 21:16:55 +00:00
|
|
|
|
var list = struct.synthetic ? synthetic_implementors : implementors;
|
|
|
|
|
|
2018-02-15 23:45:52 +00:00
|
|
|
|
if (struct.synthetic) {
|
2020-12-30 15:36:08 +00:00
|
|
|
|
for (var k = 0, stlength = struct.types.length; k < stlength; k++) {
|
2020-01-13 22:28:34 +00:00
|
|
|
|
if (inlined_types.has(struct.types[k])) {
|
2018-02-15 23:45:52 +00:00
|
|
|
|
continue struct_loop;
|
|
|
|
|
}
|
2020-01-13 22:28:34 +00:00
|
|
|
|
inlined_types.add(struct.types[k]);
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 21:16:55 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var code = document.createElement("code");
|
Generate documentation for auto-trait impls
A new section is added to both both struct and trait doc pages.
On struct/enum pages, a new 'Auto Trait Implementations' section displays any
synthetic implementations for auto traits. Currently, this is only done
for Send and Sync.
On trait pages, a new 'Auto Implementors' section displays all types
which automatically implement the trait. Effectively, this is a list of
all public types in the standard library.
Synthesized impls for a particular auto trait ('synthetic impls') take
into account generic bounds. For example, a type 'struct Foo<T>(T)' will
have 'impl<T> Send for Foo<T> where T: Send' generated for it.
Manual implementations of auto traits are also taken into account. If we have
the following types:
'struct Foo<T>(T)'
'struct Wrapper<T>(Foo<T>)'
'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes
this sound somehow
Then Wrapper will have the following impl generated:
'impl<T> Send for Wrapper<T>'
reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send'
to hold
Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are
taken into account by synthetic impls
However, if a type can *never* implement a particular auto trait
(e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be
generated (in this case, 'impl<T> !Send for MyStruct<T>')
All of this means that a user should be able to copy-paste a synthetic
impl into their code, without any observable changes in behavior
(assuming the rest of the program remains unchanged).
2017-11-22 21:16:55 +00:00
|
|
|
|
code.innerHTML = struct.text;
|
2017-04-14 14:37:09 +00:00
|
|
|
|
|
2020-12-31 12:21:27 +00:00
|
|
|
|
onEachLazy(code.getElementsByTagName("a"), function(elem) {
|
|
|
|
|
var href = elem.getAttribute("href");
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (href && href.indexOf("http") !== 0) {
|
2021-01-18 11:03:53 +00:00
|
|
|
|
elem.setAttribute("href", window.rootPath + href);
|
2014-06-01 17:17:30 +00:00
|
|
|
|
}
|
2020-12-31 12:21:27 +00:00
|
|
|
|
});
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var display = document.createElement("h3");
|
2018-07-01 14:11:14 +00:00
|
|
|
|
addClass(display, "impl");
|
2018-11-16 15:31:07 +00:00
|
|
|
|
display.innerHTML = "<span class=\"in-band\"><table class=\"table-display\">" +
|
|
|
|
|
"<tbody><tr><td><code>" + code.outerHTML + "</code></td><td></td></tr>" +
|
|
|
|
|
"</tbody></table></span>";
|
2018-07-01 14:11:14 +00:00
|
|
|
|
list.appendChild(display);
|
2014-05-21 23:41:58 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if (window.pending_implementors) {
|
|
|
|
|
window.register_implementors(window.pending_implementors);
|
|
|
|
|
}
|
2014-05-24 03:17:27 +00:00
|
|
|
|
|
2015-05-07 07:53:21 +00:00
|
|
|
|
function labelForToggleButton(sectionIsCollapsed) {
|
|
|
|
|
if (sectionIsCollapsed) {
|
|
|
|
|
// button will expand the section
|
|
|
|
|
return "+";
|
|
|
|
|
}
|
2015-05-22 12:14:28 +00:00
|
|
|
|
// button will collapse the section
|
2021-03-05 17:04:33 +00:00
|
|
|
|
// note that this text is also set in the HTML template in ../render/mod.rs
|
2018-11-16 15:31:07 +00:00
|
|
|
|
return "\u2212"; // "\u2212" is "−" minus sign
|
2015-05-07 07:53:21 +00:00
|
|
|
|
}
|
2015-05-07 08:17:10 +00:00
|
|
|
|
|
2017-04-14 14:37:09 +00:00
|
|
|
|
function onEveryMatchingChild(elem, className, func) {
|
|
|
|
|
if (elem && className && func) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var length = elem.childNodes.length;
|
|
|
|
|
var nodes = elem.childNodes;
|
|
|
|
|
for (var i = 0; i < length; ++i) {
|
|
|
|
|
if (hasClass(nodes[i], className)) {
|
|
|
|
|
func(nodes[i]);
|
2017-04-14 14:37:09 +00:00
|
|
|
|
} else {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
onEveryMatchingChild(nodes[i], className, func);
|
2017-04-14 14:37:09 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-23 13:55:24 +00:00
|
|
|
|
function toggleAllDocs(fromAutoCollapse) {
|
2020-08-29 10:38:50 +00:00
|
|
|
|
var innerToggle = document.getElementById(toggleAllDocsId);
|
2018-11-26 16:17:38 +00:00
|
|
|
|
if (!innerToggle) {
|
2018-04-25 17:50:32 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2018-11-26 16:17:38 +00:00
|
|
|
|
if (hasClass(innerToggle, "will-expand")) {
|
2018-03-01 09:50:32 +00:00
|
|
|
|
updateLocalStorage("rustdoc-collapse", "false");
|
2018-11-26 16:17:38 +00:00
|
|
|
|
removeClass(innerToggle, "will-expand");
|
|
|
|
|
onEveryMatchingChild(innerToggle, "inner", function(e) {
|
2017-04-14 14:37:09 +00:00
|
|
|
|
e.innerHTML = labelForToggleButton(false);
|
|
|
|
|
});
|
2018-11-26 16:17:38 +00:00
|
|
|
|
innerToggle.title = "collapse all docs";
|
2018-06-10 20:38:04 +00:00
|
|
|
|
if (fromAutoCollapse !== true) {
|
2018-12-02 00:22:44 +00:00
|
|
|
|
onEachLazy(document.getElementsByClassName("collapse-toggle"), function(e) {
|
2018-06-10 20:38:04 +00:00
|
|
|
|
collapseDocs(e, "show");
|
|
|
|
|
});
|
|
|
|
|
}
|
2015-05-07 07:53:21 +00:00
|
|
|
|
} else {
|
2018-03-01 09:50:32 +00:00
|
|
|
|
updateLocalStorage("rustdoc-collapse", "true");
|
2018-11-26 16:17:38 +00:00
|
|
|
|
addClass(innerToggle, "will-expand");
|
|
|
|
|
onEveryMatchingChild(innerToggle, "inner", function(e) {
|
2019-02-04 13:59:06 +00:00
|
|
|
|
var parent = e.parentNode;
|
|
|
|
|
var superParent = null;
|
|
|
|
|
|
|
|
|
|
if (parent) {
|
|
|
|
|
superParent = parent.parentNode;
|
|
|
|
|
}
|
|
|
|
|
if (!parent || !superParent || superParent.id !== "main" ||
|
|
|
|
|
hasClass(parent, "impl") === false) {
|
|
|
|
|
e.innerHTML = labelForToggleButton(true);
|
|
|
|
|
}
|
2017-04-14 14:37:09 +00:00
|
|
|
|
});
|
2018-11-26 16:17:38 +00:00
|
|
|
|
innerToggle.title = "expand all docs";
|
2018-06-10 20:38:04 +00:00
|
|
|
|
if (fromAutoCollapse !== true) {
|
2018-12-02 00:22:44 +00:00
|
|
|
|
onEachLazy(document.getElementsByClassName("collapse-toggle"), function(e) {
|
2019-02-04 13:59:06 +00:00
|
|
|
|
var parent = e.parentNode;
|
|
|
|
|
var superParent = null;
|
|
|
|
|
|
|
|
|
|
if (parent) {
|
|
|
|
|
superParent = parent.parentNode;
|
|
|
|
|
}
|
|
|
|
|
if (!parent || !superParent || superParent.id !== "main" ||
|
|
|
|
|
hasClass(parent, "impl") === false) {
|
2021-01-23 13:55:24 +00:00
|
|
|
|
collapseDocs(e, "hide");
|
2019-02-04 13:59:06 +00:00
|
|
|
|
}
|
2018-06-10 20:38:04 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
2015-04-22 16:50:19 +00:00
|
|
|
|
}
|
2016-05-21 02:21:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-23 13:55:24 +00:00
|
|
|
|
function collapseDocs(toggle, mode) {
|
2017-04-14 14:37:09 +00:00
|
|
|
|
if (!toggle || !toggle.parentNode) {
|
|
|
|
|
return;
|
2015-04-22 17:32:59 +00:00
|
|
|
|
}
|
2018-01-31 01:02:51 +00:00
|
|
|
|
|
2018-01-31 00:48:16 +00:00
|
|
|
|
function adjustToggle(arg) {
|
|
|
|
|
return function(e) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (hasClass(e, "toggle-label")) {
|
2018-01-31 00:48:16 +00:00
|
|
|
|
if (arg) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
e.style.display = "inline-block";
|
2018-01-31 00:48:16 +00:00
|
|
|
|
} else {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
e.style.display = "none";
|
2017-04-14 14:37:09 +00:00
|
|
|
|
}
|
2018-01-31 00:48:16 +00:00
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (hasClass(e, "inner")) {
|
2018-01-31 00:48:16 +00:00
|
|
|
|
e.innerHTML = labelForToggleButton(arg);
|
|
|
|
|
}
|
|
|
|
|
};
|
2018-11-16 15:31:07 +00:00
|
|
|
|
}
|
2018-01-31 01:02:51 +00:00
|
|
|
|
|
2019-02-04 14:50:46 +00:00
|
|
|
|
function implHider(addOrRemove, fullHide) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
return function(n) {
|
2020-12-07 14:13:12 +00:00
|
|
|
|
var shouldHide =
|
|
|
|
|
fullHide === true ||
|
|
|
|
|
hasClass(n, "method") === true ||
|
|
|
|
|
hasClass(n, "associatedconstant") === true;
|
|
|
|
|
if (shouldHide === true || hasClass(n, "type") === true) {
|
|
|
|
|
if (shouldHide === true) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (addOrRemove) {
|
|
|
|
|
addClass(n, "hidden-by-impl-hider");
|
|
|
|
|
} else {
|
|
|
|
|
removeClass(n, "hidden-by-impl-hider");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var ns = n.nextElementSibling;
|
2020-11-23 12:20:16 +00:00
|
|
|
|
while (ns && (hasClass(ns, "docblock") || hasClass(ns, "item-info"))) {
|
2020-05-17 13:34:59 +00:00
|
|
|
|
if (addOrRemove) {
|
|
|
|
|
addClass(ns, "hidden-by-impl-hider");
|
|
|
|
|
} else {
|
|
|
|
|
removeClass(ns, "hidden-by-impl-hider");
|
2018-11-16 15:31:07 +00:00
|
|
|
|
}
|
2020-05-17 13:34:59 +00:00
|
|
|
|
ns = ns.nextElementSibling;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var relatedDoc;
|
2018-12-02 18:11:32 +00:00
|
|
|
|
var action = mode;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (hasClass(toggle.parentNode, "impl") === false) {
|
|
|
|
|
relatedDoc = toggle.parentNode.nextElementSibling;
|
2020-11-23 12:20:16 +00:00
|
|
|
|
if (hasClass(relatedDoc, "item-info")) {
|
2018-01-31 00:48:16 +00:00
|
|
|
|
relatedDoc = relatedDoc.nextElementSibling;
|
|
|
|
|
}
|
2018-10-18 23:34:46 +00:00
|
|
|
|
if (hasClass(relatedDoc, "docblock") || hasClass(relatedDoc, "sub-variant")) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (mode === "toggle") {
|
2018-01-31 14:35:57 +00:00
|
|
|
|
if (hasClass(relatedDoc, "hidden-by-usual-hider")) {
|
|
|
|
|
action = "show";
|
2018-01-31 00:48:16 +00:00
|
|
|
|
} else {
|
2018-01-31 14:35:57 +00:00
|
|
|
|
action = "hide";
|
2017-04-14 14:37:09 +00:00
|
|
|
|
}
|
2018-01-31 00:48:16 +00:00
|
|
|
|
}
|
2018-01-31 14:35:57 +00:00
|
|
|
|
if (action === "hide") {
|
2018-01-31 00:48:16 +00:00
|
|
|
|
addClass(relatedDoc, "hidden-by-usual-hider");
|
2018-12-02 00:22:44 +00:00
|
|
|
|
onEachLazy(toggle.childNodes, adjustToggle(true));
|
2018-11-16 15:31:07 +00:00
|
|
|
|
addClass(toggle.parentNode, "collapsed");
|
2018-01-31 14:35:57 +00:00
|
|
|
|
} else if (action === "show") {
|
2018-01-31 00:48:16 +00:00
|
|
|
|
removeClass(relatedDoc, "hidden-by-usual-hider");
|
2018-11-16 15:31:07 +00:00
|
|
|
|
removeClass(toggle.parentNode, "collapsed");
|
2018-12-02 00:22:44 +00:00
|
|
|
|
onEachLazy(toggle.childNodes, adjustToggle(false));
|
2018-01-31 00:48:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2019-02-04 14:50:46 +00:00
|
|
|
|
// we are collapsing the impl block(s).
|
2018-01-31 01:02:51 +00:00
|
|
|
|
|
2018-04-04 14:16:53 +00:00
|
|
|
|
var parentElem = toggle.parentNode;
|
2018-11-16 15:31:07 +00:00
|
|
|
|
relatedDoc = parentElem;
|
2018-03-28 07:50:55 +00:00
|
|
|
|
var docblock = relatedDoc.nextElementSibling;
|
2018-01-31 01:02:51 +00:00
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
while (hasClass(relatedDoc, "impl-items") === false) {
|
2018-01-31 00:48:16 +00:00
|
|
|
|
relatedDoc = relatedDoc.nextElementSibling;
|
|
|
|
|
}
|
2018-01-31 01:02:51 +00:00
|
|
|
|
|
2020-07-09 19:42:02 +00:00
|
|
|
|
if (!relatedDoc && hasClass(docblock, "docblock") === false) {
|
2018-01-31 14:35:57 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2018-01-31 01:02:51 +00:00
|
|
|
|
|
2019-02-04 14:50:46 +00:00
|
|
|
|
// Hide all functions, but not associated types/consts.
|
2018-01-31 01:02:51 +00:00
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (mode === "toggle") {
|
2018-03-28 07:50:55 +00:00
|
|
|
|
if (hasClass(relatedDoc, "fns-now-collapsed") ||
|
2018-11-16 15:31:07 +00:00
|
|
|
|
hasClass(docblock, "hidden-by-impl-hider")) {
|
2018-01-31 14:35:57 +00:00
|
|
|
|
action = "show";
|
2018-01-31 00:48:16 +00:00
|
|
|
|
} else {
|
2018-01-31 14:35:57 +00:00
|
|
|
|
action = "hide";
|
2018-01-31 00:48:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-31 01:02:51 +00:00
|
|
|
|
|
2019-02-04 14:50:46 +00:00
|
|
|
|
var dontApplyBlockRule = toggle.parentNode.parentNode.id !== "main";
|
2018-01-31 14:35:57 +00:00
|
|
|
|
if (action === "show") {
|
2018-01-31 00:48:16 +00:00
|
|
|
|
removeClass(relatedDoc, "fns-now-collapsed");
|
2020-11-23 12:20:16 +00:00
|
|
|
|
// Stability/deprecation/portability information is never hidden.
|
|
|
|
|
if (hasClass(docblock, "item-info") === false) {
|
2020-11-22 13:45:54 +00:00
|
|
|
|
removeClass(docblock, "hidden-by-usual-hider");
|
|
|
|
|
}
|
2019-02-04 14:50:46 +00:00
|
|
|
|
onEachLazy(toggle.childNodes, adjustToggle(false, dontApplyBlockRule));
|
|
|
|
|
onEachLazy(relatedDoc.childNodes, implHider(false, dontApplyBlockRule));
|
2018-01-31 14:35:57 +00:00
|
|
|
|
} else if (action === "hide") {
|
2018-01-31 00:48:16 +00:00
|
|
|
|
addClass(relatedDoc, "fns-now-collapsed");
|
2020-11-23 12:20:16 +00:00
|
|
|
|
// Stability/deprecation/portability information should be shown even when detailed
|
|
|
|
|
// info is hidden.
|
|
|
|
|
if (hasClass(docblock, "item-info") === false) {
|
2020-11-22 13:45:54 +00:00
|
|
|
|
addClass(docblock, "hidden-by-usual-hider");
|
|
|
|
|
}
|
2019-02-08 09:47:20 +00:00
|
|
|
|
onEachLazy(toggle.childNodes, adjustToggle(true, dontApplyBlockRule));
|
2019-02-04 14:50:46 +00:00
|
|
|
|
onEachLazy(relatedDoc.childNodes, implHider(true, dontApplyBlockRule));
|
2014-07-31 01:31:34 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-06 20:06:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-01-23 13:55:24 +00:00
|
|
|
|
function collapser(e, collapse) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
// inherent impl ids are like "impl" or impl-<number>'.
|
|
|
|
|
// they will never be hidden by default.
|
|
|
|
|
var n = e.parentElement;
|
|
|
|
|
if (n.id.match(/^impl(?:-\d+)?$/) === null) {
|
|
|
|
|
// Automatically minimize all non-inherent impls
|
|
|
|
|
if (collapse || hasClass(n, "impl")) {
|
2021-01-23 13:55:24 +00:00
|
|
|
|
collapseDocs(e, "hide");
|
2018-11-16 15:31:07 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-23 13:55:24 +00:00
|
|
|
|
function autoCollapse(collapse) {
|
2018-06-10 20:38:04 +00:00
|
|
|
|
if (collapse) {
|
2021-01-23 13:55:24 +00:00
|
|
|
|
toggleAllDocs(true);
|
2020-09-23 21:14:43 +00:00
|
|
|
|
} else if (getSettingValue("auto-hide-trait-implementations") !== "false") {
|
2020-05-05 11:48:32 +00:00
|
|
|
|
var impl_list = document.getElementById("trait-implementations-list");
|
2018-09-24 20:04:23 +00:00
|
|
|
|
|
|
|
|
|
if (impl_list !== null) {
|
2018-12-02 18:11:32 +00:00
|
|
|
|
onEachLazy(impl_list.getElementsByClassName("collapse-toggle"), function(e) {
|
2021-01-23 13:55:24 +00:00
|
|
|
|
collapser(e, collapse);
|
2018-12-02 18:11:32 +00:00
|
|
|
|
});
|
2018-09-24 20:04:23 +00:00
|
|
|
|
}
|
2019-03-29 18:47:19 +00:00
|
|
|
|
|
|
|
|
|
var blanket_list = document.getElementById("blanket-implementations-list");
|
|
|
|
|
|
|
|
|
|
if (blanket_list !== null) {
|
|
|
|
|
onEachLazy(blanket_list.getElementsByClassName("collapse-toggle"), function(e) {
|
2021-01-23 13:55:24 +00:00
|
|
|
|
collapser(e, collapse);
|
2019-03-29 18:47:19 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
2018-08-01 22:19:04 +00:00
|
|
|
|
}
|
2016-11-06 20:06:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-14 14:37:09 +00:00
|
|
|
|
function insertAfter(newNode, referenceNode) {
|
|
|
|
|
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
|
|
|
|
|
}
|
2014-07-31 01:31:34 +00:00
|
|
|
|
|
2018-11-26 16:17:38 +00:00
|
|
|
|
function createSimpleToggle(sectionIsCollapsed) {
|
|
|
|
|
var toggle = document.createElement("a");
|
|
|
|
|
toggle.href = "javascript:void(0)";
|
|
|
|
|
toggle.className = "collapse-toggle";
|
|
|
|
|
toggle.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(sectionIsCollapsed) +
|
|
|
|
|
"</span>]";
|
|
|
|
|
return toggle;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 12:49:04 +00:00
|
|
|
|
function createToggle(toggle, otherMessage, fontSize, extraClass, show) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var span = document.createElement("span");
|
|
|
|
|
span.className = "toggle-label";
|
2018-08-01 22:19:04 +00:00
|
|
|
|
if (show) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
span.style.display = "none";
|
2018-08-01 22:19:04 +00:00
|
|
|
|
}
|
2018-03-27 09:57:00 +00:00
|
|
|
|
if (!otherMessage) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
span.innerHTML = " Expand description";
|
2018-03-27 09:57:00 +00:00
|
|
|
|
} else {
|
|
|
|
|
span.innerHTML = otherMessage;
|
2018-07-18 19:27:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fontSize) {
|
|
|
|
|
span.style.fontSize = fontSize;
|
2018-03-27 09:57:00 +00:00
|
|
|
|
}
|
2017-06-29 20:10:24 +00:00
|
|
|
|
|
|
|
|
|
var mainToggle = toggle.cloneNode(true);
|
|
|
|
|
mainToggle.appendChild(span);
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var wrapper = document.createElement("div");
|
|
|
|
|
wrapper.className = "toggle-wrapper";
|
2018-08-01 22:19:04 +00:00
|
|
|
|
if (!show) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
addClass(wrapper, "collapsed");
|
|
|
|
|
var inner = mainToggle.getElementsByClassName("inner");
|
2018-08-01 22:19:04 +00:00
|
|
|
|
if (inner && inner.length > 0) {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
inner[0].innerHTML = "+";
|
2018-08-01 22:19:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-05-29 23:10:48 +00:00
|
|
|
|
if (extraClass) {
|
2018-08-01 22:19:04 +00:00
|
|
|
|
addClass(wrapper, extraClass);
|
2018-05-29 23:10:48 +00:00
|
|
|
|
}
|
2017-06-29 20:10:24 +00:00
|
|
|
|
wrapper.appendChild(mainToggle);
|
|
|
|
|
return wrapper;
|
|
|
|
|
}
|
2014-12-19 18:56:47 +00:00
|
|
|
|
|
2020-05-17 12:49:04 +00:00
|
|
|
|
(function() {
|
2020-08-29 10:38:50 +00:00
|
|
|
|
var toggles = document.getElementById(toggleAllDocsId);
|
2020-08-28 11:30:21 +00:00
|
|
|
|
if (toggles) {
|
|
|
|
|
toggles.onclick = toggleAllDocs;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 12:49:04 +00:00
|
|
|
|
var toggle = createSimpleToggle(false);
|
2020-09-23 21:14:43 +00:00
|
|
|
|
var hideMethodDocs = getSettingValue("auto-hide-method-docs") === "true";
|
|
|
|
|
var hideImplementors = getSettingValue("auto-collapse-implementors") !== "false";
|
2020-05-17 12:49:04 +00:00
|
|
|
|
|
|
|
|
|
var func = function(e) {
|
|
|
|
|
var next = e.nextElementSibling;
|
2020-11-23 12:20:16 +00:00
|
|
|
|
if (next && hasClass(next, "item-info")) {
|
2020-11-02 18:17:33 +00:00
|
|
|
|
next = next.nextElementSibling;
|
|
|
|
|
}
|
2020-05-17 12:49:04 +00:00
|
|
|
|
if (!next) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-11-02 18:17:33 +00:00
|
|
|
|
if (hasClass(next, "docblock")) {
|
2020-05-17 12:49:04 +00:00
|
|
|
|
var newToggle = toggle.cloneNode(true);
|
|
|
|
|
insertAfter(newToggle, e.childNodes[e.childNodes.length - 1]);
|
|
|
|
|
if (hideMethodDocs === true && hasClass(e, "method") === true) {
|
2021-01-23 13:55:24 +00:00
|
|
|
|
collapseDocs(newToggle, "hide");
|
2019-09-22 22:49:29 +00:00
|
|
|
|
}
|
2020-05-17 12:49:04 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var funcImpl = function(e) {
|
|
|
|
|
var next = e.nextElementSibling;
|
2020-11-23 12:20:16 +00:00
|
|
|
|
if (next && hasClass(next, "item-info")) {
|
2020-11-02 18:17:33 +00:00
|
|
|
|
next = next.nextElementSibling;
|
|
|
|
|
}
|
2020-05-17 12:49:04 +00:00
|
|
|
|
if (next && hasClass(next, "docblock")) {
|
|
|
|
|
next = next.nextElementSibling;
|
|
|
|
|
}
|
|
|
|
|
if (!next) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-05-03 13:17:45 +00:00
|
|
|
|
if (hasClass(e, "impl") &&
|
|
|
|
|
(next.getElementsByClassName("method").length > 0 ||
|
|
|
|
|
next.getElementsByClassName("associatedconstant").length > 0)) {
|
2020-07-09 19:42:02 +00:00
|
|
|
|
var newToggle = toggle.cloneNode(true);
|
|
|
|
|
insertAfter(newToggle, e.childNodes[e.childNodes.length - 1]);
|
|
|
|
|
// In case the option "auto-collapse implementors" is not set to false, we collapse
|
|
|
|
|
// all implementors.
|
|
|
|
|
if (hideImplementors === true && e.parentNode.id === "implementors-list") {
|
2021-01-23 13:55:24 +00:00
|
|
|
|
collapseDocs(newToggle, "hide");
|
2020-07-09 19:42:02 +00:00
|
|
|
|
}
|
2020-05-17 12:49:04 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onEachLazy(document.getElementsByClassName("method"), func);
|
|
|
|
|
onEachLazy(document.getElementsByClassName("associatedconstant"), func);
|
|
|
|
|
onEachLazy(document.getElementsByClassName("impl"), funcImpl);
|
|
|
|
|
var impl_call = function() {};
|
|
|
|
|
if (hideMethodDocs === true) {
|
|
|
|
|
impl_call = function(e, newToggle) {
|
|
|
|
|
if (e.id.match(/^impl(?:-\d+)?$/) === null) {
|
|
|
|
|
// Automatically minimize all non-inherent impls
|
|
|
|
|
if (hasClass(e, "impl") === true) {
|
2021-01-23 13:55:24 +00:00
|
|
|
|
collapseDocs(newToggle, "hide");
|
2020-05-17 12:49:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-09-22 22:49:29 +00:00
|
|
|
|
}
|
2020-05-17 12:49:04 +00:00
|
|
|
|
var newToggle = document.createElement("a");
|
|
|
|
|
newToggle.href = "javascript:void(0)";
|
|
|
|
|
newToggle.className = "collapse-toggle hidden-default collapsed";
|
|
|
|
|
newToggle.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(true) +
|
|
|
|
|
"</span>] Show hidden undocumented items";
|
|
|
|
|
function toggleClicked() {
|
|
|
|
|
if (hasClass(this, "collapsed")) {
|
|
|
|
|
removeClass(this, "collapsed");
|
|
|
|
|
onEachLazy(this.parentNode.getElementsByClassName("hidden"), function(x) {
|
|
|
|
|
if (hasClass(x, "content") === false) {
|
|
|
|
|
removeClass(x, "hidden");
|
|
|
|
|
addClass(x, "x");
|
|
|
|
|
}
|
|
|
|
|
}, true);
|
|
|
|
|
this.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(false) +
|
|
|
|
|
"</span>] Hide undocumented items";
|
|
|
|
|
} else {
|
|
|
|
|
addClass(this, "collapsed");
|
|
|
|
|
onEachLazy(this.parentNode.getElementsByClassName("x"), function(x) {
|
|
|
|
|
if (hasClass(x, "content") === false) {
|
|
|
|
|
addClass(x, "hidden");
|
|
|
|
|
removeClass(x, "x");
|
|
|
|
|
}
|
|
|
|
|
}, true);
|
|
|
|
|
this.innerHTML = "[<span class=\"inner\">" + labelForToggleButton(true) +
|
|
|
|
|
"</span>] Show hidden undocumented items";
|
|
|
|
|
}
|
2019-09-22 22:49:29 +00:00
|
|
|
|
}
|
2020-05-17 12:49:04 +00:00
|
|
|
|
onEachLazy(document.getElementsByClassName("impl-items"), function(e) {
|
|
|
|
|
onEachLazy(e.getElementsByClassName("associatedconstant"), func);
|
2021-01-23 13:55:24 +00:00
|
|
|
|
// We transform the DOM iterator into a vec of DOM elements to prevent performance
|
|
|
|
|
// issues on webkit browsers.
|
|
|
|
|
var hiddenElems = Array.prototype.slice.call(e.getElementsByClassName("hidden"));
|
|
|
|
|
var needToggle = hiddenElems.some(function(hiddenElem) {
|
|
|
|
|
return hasClass(hiddenElem, "content") === false &&
|
|
|
|
|
hasClass(hiddenElem, "docblock") === false;
|
2020-12-31 12:21:27 +00:00
|
|
|
|
});
|
2020-05-17 12:49:04 +00:00
|
|
|
|
if (needToggle === true) {
|
|
|
|
|
var inner_toggle = newToggle.cloneNode(true);
|
|
|
|
|
inner_toggle.onclick = toggleClicked;
|
|
|
|
|
e.insertBefore(inner_toggle, e.firstChild);
|
|
|
|
|
impl_call(e.previousSibling, inner_toggle);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var currentType = document.getElementsByClassName("type-decl")[0];
|
|
|
|
|
var className = null;
|
|
|
|
|
if (currentType) {
|
|
|
|
|
currentType = currentType.getElementsByClassName("rust")[0];
|
|
|
|
|
if (currentType) {
|
|
|
|
|
currentType.classList.forEach(function(item) {
|
|
|
|
|
if (item !== "main") {
|
|
|
|
|
className = item;
|
|
|
|
|
return true;
|
2018-04-24 18:23:57 +00:00
|
|
|
|
}
|
2017-04-14 14:37:09 +00:00
|
|
|
|
});
|
2014-12-19 18:56:47 +00:00
|
|
|
|
}
|
2017-04-14 14:37:09 +00:00
|
|
|
|
}
|
2020-09-23 21:14:43 +00:00
|
|
|
|
var showItemDeclarations = getSettingValue("auto-hide-" + className);
|
2020-05-17 12:49:04 +00:00
|
|
|
|
if (showItemDeclarations === null) {
|
|
|
|
|
if (className === "enum" || className === "macro") {
|
|
|
|
|
showItemDeclarations = "false";
|
|
|
|
|
} else if (className === "struct" || className === "union" || className === "trait") {
|
|
|
|
|
showItemDeclarations = "true";
|
|
|
|
|
} else {
|
|
|
|
|
// In case we found an unknown type, we just use the "parent" value.
|
2020-09-23 21:14:43 +00:00
|
|
|
|
showItemDeclarations = getSettingValue("auto-hide-declarations");
|
2020-05-17 12:49:04 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
showItemDeclarations = showItemDeclarations === "false";
|
|
|
|
|
function buildToggleWrapper(e) {
|
|
|
|
|
if (hasClass(e, "autohide")) {
|
|
|
|
|
var wrap = e.previousElementSibling;
|
|
|
|
|
if (wrap && hasClass(wrap, "toggle-wrapper")) {
|
|
|
|
|
var inner_toggle = wrap.childNodes[0];
|
|
|
|
|
var extra = e.childNodes[0].tagName === "H3";
|
|
|
|
|
|
|
|
|
|
e.style.display = "none";
|
|
|
|
|
addClass(wrap, "collapsed");
|
|
|
|
|
onEachLazy(inner_toggle.getElementsByClassName("inner"), function(e) {
|
|
|
|
|
e.innerHTML = labelForToggleButton(true);
|
|
|
|
|
});
|
|
|
|
|
onEachLazy(inner_toggle.getElementsByClassName("toggle-label"), function(e) {
|
|
|
|
|
e.style.display = "inline-block";
|
|
|
|
|
if (extra === true) {
|
2020-05-17 13:34:59 +00:00
|
|
|
|
e.innerHTML = " Show " + e.childNodes[0].innerHTML;
|
2020-05-17 12:49:04 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (e.parentNode.id === "main") {
|
|
|
|
|
var otherMessage = "";
|
|
|
|
|
var fontSize;
|
|
|
|
|
var extraClass;
|
|
|
|
|
|
|
|
|
|
if (hasClass(e, "type-decl")) {
|
|
|
|
|
fontSize = "20px";
|
|
|
|
|
otherMessage = " Show declaration";
|
|
|
|
|
if (showItemDeclarations === false) {
|
|
|
|
|
extraClass = "collapsed";
|
|
|
|
|
}
|
|
|
|
|
} else if (hasClass(e, "sub-variant")) {
|
|
|
|
|
otherMessage = " Show fields";
|
|
|
|
|
} else if (hasClass(e, "non-exhaustive")) {
|
|
|
|
|
otherMessage = " This ";
|
|
|
|
|
if (hasClass(e, "non-exhaustive-struct")) {
|
|
|
|
|
otherMessage += "struct";
|
|
|
|
|
} else if (hasClass(e, "non-exhaustive-enum")) {
|
|
|
|
|
otherMessage += "enum";
|
|
|
|
|
} else if (hasClass(e, "non-exhaustive-variant")) {
|
|
|
|
|
otherMessage += "enum variant";
|
|
|
|
|
} else if (hasClass(e, "non-exhaustive-type")) {
|
|
|
|
|
otherMessage += "type";
|
|
|
|
|
}
|
|
|
|
|
otherMessage += " is marked as non-exhaustive";
|
|
|
|
|
} else if (hasClass(e.childNodes[0], "impl-items")) {
|
|
|
|
|
extraClass = "marg-left";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e.parentNode.insertBefore(
|
|
|
|
|
createToggle(
|
|
|
|
|
toggle,
|
|
|
|
|
otherMessage,
|
|
|
|
|
fontSize,
|
|
|
|
|
extraClass,
|
|
|
|
|
hasClass(e, "type-decl") === false || showItemDeclarations === true),
|
|
|
|
|
e);
|
|
|
|
|
if (hasClass(e, "type-decl") === true && showItemDeclarations === true) {
|
|
|
|
|
collapseDocs(e.previousSibling.childNodes[0], "toggle");
|
|
|
|
|
}
|
|
|
|
|
if (hasClass(e, "non-exhaustive") === true) {
|
|
|
|
|
collapseDocs(e.previousSibling.childNodes[0], "toggle");
|
|
|
|
|
}
|
2018-04-24 18:23:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-10-18 23:34:46 +00:00
|
|
|
|
|
2020-05-17 12:49:04 +00:00
|
|
|
|
onEachLazy(document.getElementsByClassName("docblock"), buildToggleWrapper);
|
|
|
|
|
onEachLazy(document.getElementsByClassName("sub-variant"), buildToggleWrapper);
|
2020-06-27 15:56:13 +00:00
|
|
|
|
|
2021-01-23 13:55:24 +00:00
|
|
|
|
autoCollapse(getSettingValue("collapse") === "true");
|
2020-06-27 15:56:13 +00:00
|
|
|
|
|
2021-01-23 13:55:24 +00:00
|
|
|
|
var pageId = getPageId();
|
2020-06-27 15:56:13 +00:00
|
|
|
|
if (pageId !== null) {
|
|
|
|
|
expandSection(pageId);
|
|
|
|
|
}
|
2020-05-17 12:49:04 +00:00
|
|
|
|
}());
|
2017-04-14 14:37:09 +00:00
|
|
|
|
|
2018-11-26 16:17:38 +00:00
|
|
|
|
function createToggleWrapper(tog) {
|
|
|
|
|
var span = document.createElement("span");
|
|
|
|
|
span.className = "toggle-label";
|
|
|
|
|
span.style.display = "none";
|
|
|
|
|
span.innerHTML = " Expand attributes";
|
|
|
|
|
tog.appendChild(span);
|
|
|
|
|
|
|
|
|
|
var wrapper = document.createElement("div");
|
|
|
|
|
wrapper.className = "toggle-wrapper toggle-attributes";
|
|
|
|
|
wrapper.appendChild(tog);
|
|
|
|
|
return wrapper;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-17 12:49:04 +00:00
|
|
|
|
(function() {
|
|
|
|
|
// To avoid checking on "rustdoc-item-attributes" value on every loop...
|
|
|
|
|
var itemAttributesFunc = function() {};
|
2020-09-23 21:14:43 +00:00
|
|
|
|
if (getSettingValue("auto-hide-attributes") !== "false") {
|
2020-05-17 12:49:04 +00:00
|
|
|
|
itemAttributesFunc = function(x) {
|
|
|
|
|
collapseDocs(x.previousSibling.childNodes[0], "toggle");
|
|
|
|
|
};
|
2017-09-09 13:33:57 +00:00
|
|
|
|
}
|
2020-05-17 12:49:04 +00:00
|
|
|
|
var attributesToggle = createToggleWrapper(createSimpleToggle(false));
|
|
|
|
|
onEachLazy(main.getElementsByClassName("attributes"), function(i_e) {
|
|
|
|
|
var attr_tog = attributesToggle.cloneNode(true);
|
|
|
|
|
if (hasClass(i_e, "top-attr") === true) {
|
|
|
|
|
addClass(attr_tog, "top-attr");
|
|
|
|
|
}
|
|
|
|
|
i_e.parentNode.insertBefore(attr_tog, i_e);
|
|
|
|
|
itemAttributesFunc(i_e);
|
|
|
|
|
});
|
|
|
|
|
}());
|
|
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
// To avoid checking on "rustdoc-line-numbers" value on every loop...
|
|
|
|
|
var lineNumbersFunc = function() {};
|
2020-09-23 21:14:43 +00:00
|
|
|
|
if (getSettingValue("line-numbers") === "true") {
|
2020-05-17 12:49:04 +00:00
|
|
|
|
lineNumbersFunc = function(x) {
|
|
|
|
|
var count = x.textContent.split("\n").length;
|
|
|
|
|
var elems = [];
|
|
|
|
|
for (var i = 0; i < count; ++i) {
|
|
|
|
|
elems.push(i + 1);
|
|
|
|
|
}
|
|
|
|
|
var node = document.createElement("pre");
|
|
|
|
|
addClass(node, "line-number");
|
|
|
|
|
node.innerHTML = elems.join("\n");
|
|
|
|
|
x.parentNode.insertBefore(node, x);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
onEachLazy(document.getElementsByClassName("rust-example-rendered"), function(e) {
|
|
|
|
|
if (hasClass(e, "compile_fail")) {
|
2020-05-17 13:34:59 +00:00
|
|
|
|
e.addEventListener("mouseover", function() {
|
2020-05-17 12:49:04 +00:00
|
|
|
|
this.parentElement.previousElementSibling.childNodes[0].style.color = "#f00";
|
|
|
|
|
});
|
2020-05-17 13:34:59 +00:00
|
|
|
|
e.addEventListener("mouseout", function() {
|
2020-05-17 12:49:04 +00:00
|
|
|
|
this.parentElement.previousElementSibling.childNodes[0].style.color = "";
|
|
|
|
|
});
|
|
|
|
|
} else if (hasClass(e, "ignore")) {
|
2020-05-17 13:34:59 +00:00
|
|
|
|
e.addEventListener("mouseover", function() {
|
2020-05-17 12:49:04 +00:00
|
|
|
|
this.parentElement.previousElementSibling.childNodes[0].style.color = "#ff9200";
|
|
|
|
|
});
|
2020-05-17 13:34:59 +00:00
|
|
|
|
e.addEventListener("mouseout", function() {
|
2020-05-17 12:49:04 +00:00
|
|
|
|
this.parentElement.previousElementSibling.childNodes[0].style.color = "";
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
lineNumbersFunc(e);
|
|
|
|
|
});
|
|
|
|
|
}());
|
2017-11-10 18:40:46 +00:00
|
|
|
|
|
2020-08-09 19:09:05 +00:00
|
|
|
|
onEachLazy(document.getElementsByClassName("notable-traits"), function(e) {
|
2020-07-06 19:53:44 +00:00
|
|
|
|
e.onclick = function() {
|
2020-08-09 19:09:05 +00:00
|
|
|
|
this.getElementsByClassName('notable-traits-tooltiptext')[0]
|
2020-07-15 15:58:10 +00:00
|
|
|
|
.classList.toggle("force-tooltip");
|
2020-07-06 19:53:44 +00:00
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
2019-03-02 16:17:08 +00:00
|
|
|
|
// In the search display, allows to switch between tabs.
|
|
|
|
|
function printTab(nb) {
|
|
|
|
|
if (nb === 0 || nb === 1 || nb === 2) {
|
|
|
|
|
currentTab = nb;
|
|
|
|
|
}
|
|
|
|
|
var nb_copy = nb;
|
|
|
|
|
onEachLazy(document.getElementById("titles").childNodes, function(elem) {
|
|
|
|
|
if (nb_copy === 0) {
|
|
|
|
|
addClass(elem, "selected");
|
|
|
|
|
} else {
|
|
|
|
|
removeClass(elem, "selected");
|
|
|
|
|
}
|
|
|
|
|
nb_copy -= 1;
|
|
|
|
|
});
|
|
|
|
|
onEachLazy(document.getElementById("results").childNodes, function(elem) {
|
|
|
|
|
if (nb === 0) {
|
|
|
|
|
elem.style.display = "";
|
|
|
|
|
} else {
|
|
|
|
|
elem.style.display = "none";
|
|
|
|
|
}
|
|
|
|
|
nb -= 1;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-20 14:42:44 +00:00
|
|
|
|
function putBackSearch(search_input) {
|
2019-12-22 14:42:10 +00:00
|
|
|
|
var search = getSearchElement();
|
|
|
|
|
if (search_input.value !== "" && hasClass(search, "hidden")) {
|
|
|
|
|
showSearchResults(search);
|
2018-04-20 14:42:44 +00:00
|
|
|
|
if (browserSupportsHistoryApi()) {
|
2021-01-25 12:21:12 +00:00
|
|
|
|
var extra = "?search=" + encodeURIComponent(search_input.value);
|
|
|
|
|
history.replaceState(search_input.value, "",
|
|
|
|
|
getNakedUrl() + extra + window.location.hash);
|
2018-04-20 14:42:44 +00:00
|
|
|
|
}
|
2020-11-10 14:01:01 +00:00
|
|
|
|
document.title = searchTitle;
|
2018-04-20 14:42:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-22 14:49:56 +00:00
|
|
|
|
function getSearchLoadingText() {
|
|
|
|
|
return "Loading search results...";
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-10 18:40:46 +00:00
|
|
|
|
if (search_input) {
|
|
|
|
|
search_input.onfocus = function() {
|
2018-04-20 14:42:44 +00:00
|
|
|
|
putBackSearch(this);
|
2017-11-10 18:40:46 +00:00
|
|
|
|
};
|
|
|
|
|
}
|
2017-11-23 20:19:48 +00:00
|
|
|
|
|
|
|
|
|
var params = getQueryStringParams();
|
|
|
|
|
if (params && params.search) {
|
2019-09-09 15:04:28 +00:00
|
|
|
|
var search = getSearchElement();
|
2020-08-22 14:49:56 +00:00
|
|
|
|
search.innerHTML = "<h3 style=\"text-align: center;\">" + getSearchLoadingText() + "</h3>";
|
2019-12-22 14:42:10 +00:00
|
|
|
|
showSearchResults(search);
|
2017-11-23 20:19:48 +00:00
|
|
|
|
}
|
2017-12-05 23:42:33 +00:00
|
|
|
|
|
|
|
|
|
var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
|
|
|
|
|
if (sidebar_menu) {
|
|
|
|
|
sidebar_menu.onclick = function() {
|
2018-11-16 15:31:07 +00:00
|
|
|
|
var sidebar = document.getElementsByClassName("sidebar")[0];
|
2017-12-19 23:44:44 +00:00
|
|
|
|
if (hasClass(sidebar, "mobile") === true) {
|
2017-12-05 23:42:33 +00:00
|
|
|
|
hideSidebar();
|
|
|
|
|
} else {
|
|
|
|
|
showSidebar();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (main) {
|
2018-12-02 18:11:32 +00:00
|
|
|
|
onEachLazy(main.getElementsByClassName("loading-content"), function(e) {
|
|
|
|
|
e.remove();
|
|
|
|
|
});
|
2018-12-02 00:22:44 +00:00
|
|
|
|
onEachLazy(main.childNodes, function(e) {
|
2018-12-27 05:23:05 +00:00
|
|
|
|
// Unhide the actual content once loading is complete. Headers get
|
|
|
|
|
// flex treatment for their horizontal layout, divs get block treatment
|
|
|
|
|
// for vertical layout (column-oriented flex layout for divs caused
|
|
|
|
|
// errors in mobile browsers).
|
2018-11-16 15:31:07 +00:00
|
|
|
|
if (e.tagName === "H2" || e.tagName === "H3") {
|
2019-02-08 11:38:47 +00:00
|
|
|
|
var nextTagName = e.nextElementSibling.tagName;
|
2018-12-27 05:23:05 +00:00
|
|
|
|
if (nextTagName == "H2" || nextTagName == "H3") {
|
|
|
|
|
e.nextElementSibling.style.display = "flex";
|
|
|
|
|
} else {
|
|
|
|
|
e.nextElementSibling.style.display = "block";
|
|
|
|
|
}
|
2018-11-16 15:31:07 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
2018-08-05 16:22:44 +00:00
|
|
|
|
}
|
2018-09-30 22:47:54 +00:00
|
|
|
|
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
function addSearchOptions(crates) {
|
2019-07-24 15:50:48 +00:00
|
|
|
|
var elem = document.getElementById("crate-search");
|
2018-09-30 22:47:54 +00:00
|
|
|
|
|
|
|
|
|
if (!elem) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-09-23 21:14:43 +00:00
|
|
|
|
var savedCrate = getSettingValue("saved-filter-crate");
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
for (var i = 0, len = crates.length; i < len; ++i) {
|
2018-09-30 22:47:54 +00:00
|
|
|
|
var option = document.createElement("option");
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
option.value = crates[i];
|
|
|
|
|
option.innerText = crates[i];
|
2018-09-30 22:47:54 +00:00
|
|
|
|
elem.appendChild(option);
|
2019-11-18 13:11:21 +00:00
|
|
|
|
// Set the crate filter from saved storage, if the current page has the saved crate
|
|
|
|
|
// filter.
|
|
|
|
|
//
|
|
|
|
|
// If not, ignore the crate filter -- we want to support filtering for crates on sites
|
|
|
|
|
// like doc.rust-lang.org where the crates may differ from page to page while on the
|
|
|
|
|
// same domain.
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
if (crates[i] === savedCrate) {
|
2019-11-18 13:11:21 +00:00
|
|
|
|
elem.value = savedCrate;
|
|
|
|
|
}
|
2018-09-30 22:47:54 +00:00
|
|
|
|
}
|
2020-05-17 12:57:19 +00:00
|
|
|
|
};
|
2019-10-24 22:35:45 +00:00
|
|
|
|
|
|
|
|
|
function buildHelperPopup() {
|
|
|
|
|
var popup = document.createElement("aside");
|
|
|
|
|
addClass(popup, "hidden");
|
|
|
|
|
popup.id = "help";
|
|
|
|
|
|
2020-10-19 11:44:27 +00:00
|
|
|
|
var book_info = document.createElement("span");
|
|
|
|
|
book_info.innerHTML = "You can find more information in \
|
|
|
|
|
<a href=\"https://doc.rust-lang.org/rustdoc/\">the rustdoc book</a>.";
|
|
|
|
|
|
2019-10-24 22:35:45 +00:00
|
|
|
|
var container = document.createElement("div");
|
|
|
|
|
var shortcuts = [
|
|
|
|
|
["?", "Show this help dialog"],
|
|
|
|
|
["S", "Focus the search field"],
|
2020-11-05 13:24:45 +00:00
|
|
|
|
["T", "Focus the theme picker menu"],
|
2019-10-24 22:35:45 +00:00
|
|
|
|
["↑", "Move up in search results"],
|
|
|
|
|
["↓", "Move down in search results"],
|
2020-12-09 19:47:55 +00:00
|
|
|
|
["ctrl + ↑ / ↓", "Switch result tab"],
|
2019-10-24 22:35:45 +00:00
|
|
|
|
["⏎", "Go to active search result"],
|
|
|
|
|
["+", "Expand all sections"],
|
|
|
|
|
["-", "Collapse all sections"],
|
2021-02-15 09:11:37 +00:00
|
|
|
|
].map(function(x) {
|
|
|
|
|
return "<dt>" +
|
|
|
|
|
x[0].split(" ")
|
|
|
|
|
.map(function(y, index) {
|
|
|
|
|
return (index & 1) === 0 ? "<kbd>" + y + "</kbd>" : " " + y + " ";
|
|
|
|
|
})
|
|
|
|
|
.join("") + "</dt><dd>" + x[1] + "</dd>";
|
|
|
|
|
}).join("");
|
2019-10-24 22:35:45 +00:00
|
|
|
|
var div_shortcuts = document.createElement("div");
|
|
|
|
|
addClass(div_shortcuts, "shortcuts");
|
|
|
|
|
div_shortcuts.innerHTML = "<h2>Keyboard Shortcuts</h2><dl>" + shortcuts + "</dl></div>";
|
|
|
|
|
|
|
|
|
|
var infos = [
|
|
|
|
|
"Prefix searches with a type followed by a colon (e.g., <code>fn:</code>) to \
|
2020-08-27 10:56:43 +00:00
|
|
|
|
restrict the search to a given item kind.",
|
|
|
|
|
"Accepted kinds are: <code>fn</code>, <code>mod</code>, <code>struct</code>, \
|
2019-10-24 22:35:45 +00:00
|
|
|
|
<code>enum</code>, <code>trait</code>, <code>type</code>, <code>macro</code>, \
|
|
|
|
|
and <code>const</code>.",
|
2020-01-12 23:37:47 +00:00
|
|
|
|
"Search functions by type signature (e.g., <code>vec -> usize</code> or \
|
|
|
|
|
<code>* -> vec</code>)",
|
2019-10-24 22:35:45 +00:00
|
|
|
|
"Search multiple things at once by splitting your query with comma (e.g., \
|
|
|
|
|
<code>str,u8</code> or <code>String,struct:Vec,test</code>)",
|
|
|
|
|
"You can look for items with an exact name by putting double quotes around \
|
|
|
|
|
your request: <code>\"string\"</code>",
|
|
|
|
|
"Look for items inside another one by searching for a path: <code>vec::Vec</code>",
|
2021-02-15 09:11:37 +00:00
|
|
|
|
].map(function(x) {
|
|
|
|
|
return "<p>" + x + "</p>";
|
|
|
|
|
}).join("");
|
2019-10-24 22:35:45 +00:00
|
|
|
|
var div_infos = document.createElement("div");
|
|
|
|
|
addClass(div_infos, "infos");
|
|
|
|
|
div_infos.innerHTML = "<h2>Search Tricks</h2>" + infos;
|
|
|
|
|
|
2020-10-19 11:44:27 +00:00
|
|
|
|
container.appendChild(book_info);
|
2019-10-24 22:35:45 +00:00
|
|
|
|
container.appendChild(div_shortcuts);
|
|
|
|
|
container.appendChild(div_infos);
|
|
|
|
|
|
|
|
|
|
popup.appendChild(container);
|
|
|
|
|
insertAfter(popup, getSearchElement());
|
2020-08-27 11:34:35 +00:00
|
|
|
|
// So that it's only built once and then it'll do nothing when called!
|
|
|
|
|
buildHelperPopup = function() {};
|
2019-10-24 22:35:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
function loadScript(url) {
|
|
|
|
|
var script = document.createElement('script');
|
|
|
|
|
script.src = url;
|
|
|
|
|
document.head.append(script);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setupSearchLoader() {
|
|
|
|
|
var searchLoaded = false;
|
|
|
|
|
function loadSearch() {
|
|
|
|
|
if (!searchLoaded) {
|
|
|
|
|
searchLoaded = true;
|
|
|
|
|
loadScript(window.searchJS);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `crates{version}.js` should always be loaded before this script, so we can use it safely.
|
|
|
|
|
addSearchOptions(window.ALL_CRATES);
|
|
|
|
|
addSidebarCrates(window.ALL_CRATES);
|
|
|
|
|
|
|
|
|
|
search_input.addEventListener("focus", function() {
|
|
|
|
|
search_input.origPlaceholder = search_input.placeholder;
|
|
|
|
|
search_input.placeholder = "Type your search here.";
|
|
|
|
|
loadSearch();
|
|
|
|
|
});
|
|
|
|
|
search_input.addEventListener("blur", function() {
|
|
|
|
|
search_input.placeholder = search_input.origPlaceholder;
|
|
|
|
|
});
|
2021-03-05 17:04:33 +00:00
|
|
|
|
search_input.removeAttribute('disabled');
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
|
|
|
|
|
var crateSearchDropDown = document.getElementById("crate-search");
|
2021-03-11 20:13:42 +00:00
|
|
|
|
// `crateSearchDropDown` can be null in case there is only crate because in that case, the
|
|
|
|
|
// crate filter dropdown is removed.
|
|
|
|
|
if (crateSearchDropDown) {
|
|
|
|
|
crateSearchDropDown.addEventListener("focus", loadSearch);
|
|
|
|
|
}
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
var params = getQueryStringParams();
|
|
|
|
|
if (params.search !== undefined) {
|
|
|
|
|
loadSearch();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-15 20:27:25 +00:00
|
|
|
|
onHashChange(null);
|
2019-11-05 16:41:40 +00:00
|
|
|
|
window.onhashchange = onHashChange;
|
Load rustdoc's JS search index on-demand.
Instead of being loaded on every page, the JS search index is now
loaded when either (a) there is a `?search=` param, or (b) the search
input is focused.
This saves both CPU and bandwidth. As of Feb 2021,
https://doc.rust-lang.org/search-index1.50.0.js is 273,838 bytes
gzipped or 2,544,939 bytes uncompressed. Evaluating it takes 445 ms
of CPU time in Chrome 88 on a i7-10710U CPU (out of a total ~2,100
ms page reload).
Generate separate JS file with crate names.
This is much smaller than the full search index, and is used in the "hot
path" to draw the page. In particular it's used to crate the dropdown
for the search bar, and to append a list of crates to the sidebar (on
some pages).
Skip early search that can bypass 500ms timeout.
This was occurring when someone had typed some text during the load of
search-index.js. Their query was usually not ready to execute, and the
search itself is fairly expensive, delaying the overall load, which
delayed the input / keyup events, which delayed eventually executing the
query.
2021-02-20 01:22:30 +00:00
|
|
|
|
setupSearchLoader();
|
2014-01-15 01:09:50 +00:00
|
|
|
|
}());
|