Rollup merge of #136161 - notriddle:typescript, r=GuillaumeGomez
rustdoc: add nobuild typescript checking to our JS By nobuild, I mean that the type annotations are all [in comments], not in the "native" typescript syntax. This is a bit uglier, but it lets you rapid-prototype without tsc, works with all the native browser debugging tools, and keeps Node out of Rust's bootstrap chain. [in comments]: https://news.ycombinator.com/item?id=35892250 This pull request mostly just adds ts-ignore annotations and type declarations. To actually take good advantage of typescript, we'll want to "burn down" this pile of unsafe code until we eventually have a version with almost none of these. This PR also adds tsc to the mingw-check Dockerfile, so that it can't fall out of date like the Closure annotations did. https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/typescript r? `@GuillaumeGomez` `@lolbinarycat`
This commit is contained in:
commit
3cc6ea2ac6
11 changed files with 1658 additions and 682 deletions
|
@ -29,7 +29,7 @@ ENV PATH="/node/bin:${PATH}"
|
||||||
|
|
||||||
# Install es-check
|
# Install es-check
|
||||||
# Pin its version to prevent unrelated CI failures due to future es-check versions.
|
# Pin its version to prevent unrelated CI failures due to future es-check versions.
|
||||||
RUN npm install es-check@6.1.1 eslint@8.6.0 -g
|
RUN npm install es-check@6.1.1 eslint@8.6.0 typescript@5.7.3 -g
|
||||||
|
|
||||||
COPY scripts/sccache.sh /scripts/
|
COPY scripts/sccache.sh /scripts/
|
||||||
RUN sh /scripts/sccache.sh
|
RUN sh /scripts/sccache.sh
|
||||||
|
@ -68,4 +68,5 @@ ENV SCRIPT \
|
||||||
es-check es2019 ../src/librustdoc/html/static/js/*.js && \
|
es-check es2019 ../src/librustdoc/html/static/js/*.js && \
|
||||||
eslint -c ../src/librustdoc/html/static/.eslintrc.js ../src/librustdoc/html/static/js/*.js && \
|
eslint -c ../src/librustdoc/html/static/.eslintrc.js ../src/librustdoc/html/static/js/*.js && \
|
||||||
eslint -c ../src/tools/rustdoc-js/.eslintrc.js ../src/tools/rustdoc-js/tester.js && \
|
eslint -c ../src/tools/rustdoc-js/.eslintrc.js ../src/tools/rustdoc-js/tester.js && \
|
||||||
eslint -c ../src/tools/rustdoc-gui/.eslintrc.js ../src/tools/rustdoc-gui/tester.js
|
eslint -c ../src/tools/rustdoc-gui/.eslintrc.js ../src/tools/rustdoc-gui/tester.js && \
|
||||||
|
tsc --project ../src/librustdoc/html/static/js/tsconfig.json
|
||||||
|
|
|
@ -3,13 +3,9 @@
|
||||||
These JavaScript files are incorporated into the rustdoc binary at build time,
|
These JavaScript files are incorporated into the rustdoc binary at build time,
|
||||||
and are minified and written to the filesystem as part of the doc build process.
|
and are minified and written to the filesystem as part of the doc build process.
|
||||||
|
|
||||||
We use the [Closure Compiler](https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler)
|
We use the [TypeScript Compiler](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html)
|
||||||
dialect of JSDoc to comment our code and annotate params and return types.
|
dialect of JSDoc to comment our code and annotate params and return types.
|
||||||
To run a check:
|
To run a check:
|
||||||
|
|
||||||
./x.py doc library/std
|
npm i -g typescript
|
||||||
npm i -g google-closure-compiler
|
tsc --project tsconfig.json
|
||||||
google-closure-compiler -W VERBOSE \
|
|
||||||
build/<YOUR PLATFORM>/doc/{search-index*.js,crates*.js} \
|
|
||||||
src/librustdoc/html/static/js/{search.js,main.js,storage.js} \
|
|
||||||
--externs src/librustdoc/html/static/js/externs.js >/dev/null
|
|
||||||
|
|
|
@ -1,270 +0,0 @@
|
||||||
// This file contains type definitions that are processed by the Closure Compiler but are
|
|
||||||
// not put into the JavaScript we include as part of the documentation. It is used for
|
|
||||||
// type checking. See README.md in this directory for more info.
|
|
||||||
|
|
||||||
/* eslint-disable */
|
|
||||||
let searchState;
|
|
||||||
function initSearch(searchIndex){}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {{
|
|
||||||
* name: string,
|
|
||||||
* id: number|null,
|
|
||||||
* fullPath: Array<string>,
|
|
||||||
* pathWithoutLast: Array<string>,
|
|
||||||
* pathLast: string,
|
|
||||||
* generics: Array<QueryElement>,
|
|
||||||
* bindings: Map<number, Array<QueryElement>>,
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
let QueryElement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {{
|
|
||||||
* pos: number,
|
|
||||||
* totalElems: number,
|
|
||||||
* typeFilter: (null|string),
|
|
||||||
* userQuery: string,
|
|
||||||
* isInBinding: (null|string),
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
let ParserState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {{
|
|
||||||
* original: string,
|
|
||||||
* userQuery: string,
|
|
||||||
* typeFilter: number,
|
|
||||||
* elems: Array<QueryElement>,
|
|
||||||
* args: Array<QueryElement>,
|
|
||||||
* returned: Array<QueryElement>,
|
|
||||||
* foundElems: number,
|
|
||||||
* totalElems: number,
|
|
||||||
* literalSearch: boolean,
|
|
||||||
* hasReturnArrow: boolean,
|
|
||||||
* corrections: Array<{from: string, to: integer}> | null,
|
|
||||||
* typeFingerprint: Uint32Array,
|
|
||||||
* error: Array<string> | null,
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
let ParsedQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {{
|
|
||||||
* crate: string,
|
|
||||||
* desc: string,
|
|
||||||
* id: number,
|
|
||||||
* name: string,
|
|
||||||
* normalizedName: string,
|
|
||||||
* parent: (Object|null|undefined),
|
|
||||||
* path: string,
|
|
||||||
* ty: (Number|null|number),
|
|
||||||
* type: FunctionSearchType?
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
let Row;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {{
|
|
||||||
* in_args: Array<Object>,
|
|
||||||
* returned: Array<Object>,
|
|
||||||
* others: Array<Object>,
|
|
||||||
* query: ParsedQuery,
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
let ResultsTable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Map<String, ResultObject>}
|
|
||||||
*/
|
|
||||||
let Results;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {{
|
|
||||||
* desc: string,
|
|
||||||
* displayPath: string,
|
|
||||||
* fullPath: string,
|
|
||||||
* href: string,
|
|
||||||
* id: number,
|
|
||||||
* lev: number,
|
|
||||||
* name: string,
|
|
||||||
* normalizedName: string,
|
|
||||||
* parent: (Object|undefined),
|
|
||||||
* path: string,
|
|
||||||
* ty: number,
|
|
||||||
* type: FunctionSearchType?,
|
|
||||||
* displayType: Promise<Array<Array<string>>>|null,
|
|
||||||
* displayTypeMappedNames: Promise<Array<[string, Array<string>]>>|null,
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
let ResultObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A pair of [inputs, outputs], or 0 for null. This is stored in the search index.
|
|
||||||
* The JavaScript deserializes this into FunctionSearchType.
|
|
||||||
*
|
|
||||||
* Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null`
|
|
||||||
* because `null` is four bytes while `0` is one byte.
|
|
||||||
*
|
|
||||||
* An input or output can be encoded as just a number if there is only one of them, AND
|
|
||||||
* it has no generics. The no generics rule exists to avoid ambiguity: imagine if you had
|
|
||||||
* a function with a single output, and that output had a single generic:
|
|
||||||
*
|
|
||||||
* fn something() -> Result<usize, usize>
|
|
||||||
*
|
|
||||||
* If output was allowed to be any RawFunctionType, it would look like thi
|
|
||||||
*
|
|
||||||
* [[], [50, [3, 3]]]
|
|
||||||
*
|
|
||||||
* The problem is that the above output could be interpreted as either a type with ID 50 and two
|
|
||||||
* generics, or it could be interpreted as a pair of types, the first one with ID 50 and the second
|
|
||||||
* with ID 3 and a single generic parameter that is also ID 3. We avoid this ambiguity by choosing
|
|
||||||
* in favor of the pair of types interpretation. This is why the `(number|Array<RawFunctionType>)`
|
|
||||||
* is used instead of `(RawFunctionType|Array<RawFunctionType>)`.
|
|
||||||
*
|
|
||||||
* The output can be skipped if it's actually unit and there's no type constraints. If thi
|
|
||||||
* function accepts constrained generics, then the output will be unconditionally emitted, and
|
|
||||||
* after it will come a list of trait constraints. The position of the item in the list will
|
|
||||||
* determine which type parameter it is. For example:
|
|
||||||
*
|
|
||||||
* [1, 2, 3, 4, 5]
|
|
||||||
* ^ ^ ^ ^ ^
|
|
||||||
* | | | | - generic parameter (-3) of trait 5
|
|
||||||
* | | | - generic parameter (-2) of trait 4
|
|
||||||
* | | - generic parameter (-1) of trait 3
|
|
||||||
* | - this function returns a single value (type 2)
|
|
||||||
* - this function takes a single input parameter (type 1)
|
|
||||||
*
|
|
||||||
* Or, for a less contrived version:
|
|
||||||
*
|
|
||||||
* [[[4, -1], 3], [[5, -1]], 11]
|
|
||||||
* -^^^^^^^---- ^^^^^^^ ^^
|
|
||||||
* | | | - generic parameter, roughly `where -1: 11`
|
|
||||||
* | | | since -1 is the type parameter and 11 the trait
|
|
||||||
* | | - function output 5<-1>
|
|
||||||
* | - the overall function signature is something like
|
|
||||||
* | `fn(4<-1>, 3) -> 5<-1> where -1: 11`
|
|
||||||
* - function input, corresponds roughly to 4<-1>
|
|
||||||
* 4 is an index into the `p` array for a type
|
|
||||||
* -1 is the generic parameter, given by 11
|
|
||||||
*
|
|
||||||
* If a generic parameter has multiple trait constraints, it gets wrapped in an array, just like
|
|
||||||
* function inputs and outputs:
|
|
||||||
*
|
|
||||||
* [-1, -1, [4, 3]]
|
|
||||||
* ^^^^^^ where -1: 4 + 3
|
|
||||||
*
|
|
||||||
* If a generic parameter's trait constraint has generic parameters, it gets wrapped in the array
|
|
||||||
* even if only one exists. In other words, the ambiguity of `4<3>` and `4 + 3` is resolved in
|
|
||||||
* favor of `4 + 3`:
|
|
||||||
*
|
|
||||||
* [-1, -1, [[4, 3]]]
|
|
||||||
* ^^^^^^^^ where -1: 4 + 3
|
|
||||||
*
|
|
||||||
* [-1, -1, [5, [4, 3]]]
|
|
||||||
* ^^^^^^^^^^^ where -1: 5, -2: 4 + 3
|
|
||||||
*
|
|
||||||
* If a generic parameter has no trait constraints (like in Rust, the `Sized` constraint i
|
|
||||||
* implied and a fake `?Sized` constraint used to note its absence), it will be filled in with 0.
|
|
||||||
*
|
|
||||||
* @typedef {(
|
|
||||||
* 0 |
|
|
||||||
* [(number|Array<RawFunctionType>)] |
|
|
||||||
* [(number|Array<RawFunctionType>), (number|Array<RawFunctionType>)] |
|
|
||||||
* Array<(number|Array<RawFunctionType>)>
|
|
||||||
* )}
|
|
||||||
*/
|
|
||||||
let RawFunctionSearchType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A single function input or output type. This is either a single path ID, or a pair of
|
|
||||||
* [path ID, generics].
|
|
||||||
*
|
|
||||||
* Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null`
|
|
||||||
* because `null` is four bytes while `0` is one byte.
|
|
||||||
*
|
|
||||||
* @typedef {number | [number, Array<RawFunctionType>]}
|
|
||||||
*/
|
|
||||||
let RawFunctionType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {{
|
|
||||||
* inputs: Array<FunctionType>,
|
|
||||||
* output: Array<FunctionType>,
|
|
||||||
* where_clause: Array<Array<FunctionType>>,
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
let FunctionSearchType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {{
|
|
||||||
* id: (null|number),
|
|
||||||
* ty: number,
|
|
||||||
* generics: Array<FunctionType>,
|
|
||||||
* bindings: Map<integer, Array<FunctionType>>,
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
let FunctionType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The raw search data for a given crate. `n`, `t`, `d`, `i`, and `f`
|
|
||||||
* are arrays with the same length. `q`, `a`, and `c` use a sparse
|
|
||||||
* representation for compactness.
|
|
||||||
*
|
|
||||||
* `n[i]` contains the name of an item.
|
|
||||||
*
|
|
||||||
* `t[i]` contains the type of that item
|
|
||||||
* (as a string of characters that represent an offset in `itemTypes`).
|
|
||||||
*
|
|
||||||
* `d[i]` contains the description of that item.
|
|
||||||
*
|
|
||||||
* `q` contains the full paths of the items. For compactness, it is a set of
|
|
||||||
* (index, path) pairs used to create a map. If a given index `i` is
|
|
||||||
* not present, this indicates "same as the last index present".
|
|
||||||
*
|
|
||||||
* `i[i]` contains an item's parent, usually a module. For compactness,
|
|
||||||
* it is a set of indexes into the `p` array.
|
|
||||||
*
|
|
||||||
* `f` contains function signatures, or `0` if the item isn't a function.
|
|
||||||
* More information on how they're encoded can be found in rustc-dev-guide
|
|
||||||
*
|
|
||||||
* Functions are themselves encoded as arrays. The first item is a list of
|
|
||||||
* types representing the function's inputs, and the second list item is a list
|
|
||||||
* of types representing the function's output. Tuples are flattened.
|
|
||||||
* Types are also represented as arrays; the first item is an index into the `p`
|
|
||||||
* array, while the second is a list of types representing any generic parameters.
|
|
||||||
*
|
|
||||||
* b[i] contains an item's impl disambiguator. This is only present if an item
|
|
||||||
* is defined in an impl block and, the impl block's type has more than one associated
|
|
||||||
* item with the same name.
|
|
||||||
*
|
|
||||||
* `a` defines aliases with an Array of pairs: [name, offset], where `offset`
|
|
||||||
* points into the n/t/d/q/i/f arrays.
|
|
||||||
*
|
|
||||||
* `doc` contains the description of the crate.
|
|
||||||
*
|
|
||||||
* `p` is a list of path/type pairs. It is used for parents and function parameters.
|
|
||||||
* The first item is the type, the second is the name, the third is the visible path (if any) and
|
|
||||||
* the fourth is the canonical path used for deduplication (if any).
|
|
||||||
*
|
|
||||||
* `r` is the canonical path used for deduplication of re-exported items.
|
|
||||||
* It is not used for associated items like methods (that's the fourth element
|
|
||||||
* of `p`) but is used for modules items like free functions.
|
|
||||||
*
|
|
||||||
* `c` is an array of item indices that are deprecated.
|
|
||||||
* @typedef {{
|
|
||||||
* doc: string,
|
|
||||||
* a: Object,
|
|
||||||
* n: Array<string>,
|
|
||||||
* t: string,
|
|
||||||
* d: Array<string>,
|
|
||||||
* q: Array<[number, string]>,
|
|
||||||
* i: Array<number>,
|
|
||||||
* f: string,
|
|
||||||
* p: Array<[number, string] | [number, string, number] | [number, string, number, number]>,
|
|
||||||
* b: Array<[number, String]>,
|
|
||||||
* c: Array<number>,
|
|
||||||
* r: Array<[number, number]>,
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
let RawSearchIndexCrate;
|
|
File diff suppressed because it is too large
Load diff
387
src/librustdoc/html/static/js/rustdoc.d.ts
vendored
Normal file
387
src/librustdoc/html/static/js/rustdoc.d.ts
vendored
Normal file
|
@ -0,0 +1,387 @@
|
||||||
|
// This file contains type definitions that are processed by the TypeScript Compiler but are
|
||||||
|
// not put into the JavaScript we include as part of the documentation. It is used for
|
||||||
|
// type checking. See README.md in this directory for more info.
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
/** Make the current theme easy to find */
|
||||||
|
currentTheme: HTMLLinkElement|null;
|
||||||
|
/** Used by the popover tooltip code. */
|
||||||
|
RUSTDOC_TOOLTIP_HOVER_MS: number;
|
||||||
|
/** Used by the popover tooltip code. */
|
||||||
|
RUSTDOC_TOOLTIP_HOVER_EXIT_MS: number;
|
||||||
|
/** Search engine data used by main.js and search.js */
|
||||||
|
searchState: rustdoc.SearchState;
|
||||||
|
/** Global option, with a long list of "../"'s */
|
||||||
|
rootPath: string|null;
|
||||||
|
/**
|
||||||
|
* Currently opened crate.
|
||||||
|
* As a multi-page application, we know this never changes once set.
|
||||||
|
*/
|
||||||
|
currentCrate: string|null;
|
||||||
|
}
|
||||||
|
interface HTMLElement {
|
||||||
|
/** Used by the popover tooltip code. */
|
||||||
|
TOOLTIP_FORCE_VISIBLE: boolean|undefined,
|
||||||
|
/** Used by the popover tooltip code */
|
||||||
|
TOOLTIP_HOVER_TIMEOUT: Timeout|undefined,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export = rustdoc;
|
||||||
|
|
||||||
|
declare namespace rustdoc {
|
||||||
|
interface SearchState {
|
||||||
|
rustdocToolbar: HTMLElement|null;
|
||||||
|
loadingText: string;
|
||||||
|
input: HTMLInputElement|null;
|
||||||
|
title: string;
|
||||||
|
titleBeforeSearch: string;
|
||||||
|
timeout: number|null;
|
||||||
|
currentTab: number;
|
||||||
|
focusedByTab: [number|null, number|null, number|null];
|
||||||
|
clearInputTimeout: function;
|
||||||
|
outputElement: function(): HTMLElement|null;
|
||||||
|
focus: function();
|
||||||
|
defocus: function();
|
||||||
|
showResults: function(HTMLElement|null|undefined);
|
||||||
|
removeQueryParameters: function();
|
||||||
|
hideResults: function();
|
||||||
|
getQueryStringParams: function(): Object.<any, string>;
|
||||||
|
origPlaceholder: string;
|
||||||
|
setup: function();
|
||||||
|
setLoadingSearch: function();
|
||||||
|
descShards: Map<string, SearchDescShard[]>;
|
||||||
|
loadDesc: function({descShard: SearchDescShard, descIndex: number}): Promise<string|null>;
|
||||||
|
loadedDescShard: function(string, number, string);
|
||||||
|
isDisplayed: function(): boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SearchDescShard {
|
||||||
|
crate: string;
|
||||||
|
promise: Promise<string[]>|null;
|
||||||
|
resolve: function(string[])|null;
|
||||||
|
shard: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single parsed "atom" in a search query. For example,
|
||||||
|
*
|
||||||
|
* std::fmt::Formatter, Write -> Result<()>
|
||||||
|
* ┏━━━━━━━━━━━━━━━━━━ ┌──── ┏━━━━━┅┅┅┅┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐
|
||||||
|
* ┃ │ ┗ QueryElement { ┊
|
||||||
|
* ┃ │ name: Result ┊
|
||||||
|
* ┃ │ generics: [ ┊
|
||||||
|
* ┃ │ QueryElement ┘
|
||||||
|
* ┃ │ name: ()
|
||||||
|
* ┃ │ ]
|
||||||
|
* ┃ │ }
|
||||||
|
* ┃ └ QueryElement {
|
||||||
|
* ┃ name: Write
|
||||||
|
* ┃ }
|
||||||
|
* ┗ QueryElement {
|
||||||
|
* name: Formatter
|
||||||
|
* pathWithoutLast: std::fmt
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
interface QueryElement {
|
||||||
|
name: string,
|
||||||
|
id: number|null,
|
||||||
|
fullPath: Array<string>,
|
||||||
|
pathWithoutLast: Array<string>,
|
||||||
|
pathLast: string,
|
||||||
|
normalizedPathLast: string,
|
||||||
|
generics: Array<QueryElement>,
|
||||||
|
bindings: Map<number, Array<QueryElement>>,
|
||||||
|
typeFilter: number|null,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as QueryElement, but bindings and typeFilter support strings
|
||||||
|
*/
|
||||||
|
interface ParserQueryElement {
|
||||||
|
name: string,
|
||||||
|
id: number|null,
|
||||||
|
fullPath: Array<string>,
|
||||||
|
pathWithoutLast: Array<string>,
|
||||||
|
pathLast: string,
|
||||||
|
normalizedPathLast: string,
|
||||||
|
generics: Array<ParserQueryElement>,
|
||||||
|
bindings: Map<string, Array<ParserQueryElement>>,
|
||||||
|
bindingName: {name: string, generics: ParserQueryElement[]}|null,
|
||||||
|
typeFilter: string|null,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intermediate parser state. Discarded when parsing is done.
|
||||||
|
*/
|
||||||
|
interface ParserState {
|
||||||
|
pos: number;
|
||||||
|
length: number;
|
||||||
|
totalElems: number;
|
||||||
|
genericsElems: number;
|
||||||
|
typeFilter: (null|string);
|
||||||
|
userQuery: string;
|
||||||
|
isInBinding: (null|{name: string, generics: ParserQueryElement[]});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A complete parsed query.
|
||||||
|
*/
|
||||||
|
interface ParsedQuery<T> {
|
||||||
|
userQuery: string,
|
||||||
|
elems: Array<T>,
|
||||||
|
returned: Array<T>,
|
||||||
|
foundElems: number,
|
||||||
|
totalElems: number,
|
||||||
|
literalSearch: boolean,
|
||||||
|
hasReturnArrow: boolean,
|
||||||
|
correction: string|null,
|
||||||
|
proposeCorrectionFrom: string|null,
|
||||||
|
proposeCorrectionTo: string|null,
|
||||||
|
typeFingerprint: Uint32Array,
|
||||||
|
error: Array<string> | null,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An entry in the search index database.
|
||||||
|
*/
|
||||||
|
interface Row {
|
||||||
|
crate: string,
|
||||||
|
descShard: SearchDescShard,
|
||||||
|
id: number,
|
||||||
|
name: string,
|
||||||
|
normalizedName: string,
|
||||||
|
word: string,
|
||||||
|
parent: ({ty: number, name: string, path: string, exactPath: string}|null|undefined),
|
||||||
|
path: string,
|
||||||
|
ty: number,
|
||||||
|
type?: FunctionSearchType
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The viewmodel for the search engine results page.
|
||||||
|
*/
|
||||||
|
interface ResultsTable {
|
||||||
|
in_args: Array<ResultObject>,
|
||||||
|
returned: Array<ResultObject>,
|
||||||
|
others: Array<ResultObject>,
|
||||||
|
query: ParsedQuery,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Results = Map<String, ResultObject>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An annotated `Row`, used in the viewmodel.
|
||||||
|
*/
|
||||||
|
interface ResultObject {
|
||||||
|
desc: string,
|
||||||
|
displayPath: string,
|
||||||
|
fullPath: string,
|
||||||
|
href: string,
|
||||||
|
id: number,
|
||||||
|
dist: number,
|
||||||
|
path_dist: number,
|
||||||
|
name: string,
|
||||||
|
normalizedName: string,
|
||||||
|
word: string,
|
||||||
|
index: number,
|
||||||
|
parent: (Object|undefined),
|
||||||
|
path: string,
|
||||||
|
ty: number,
|
||||||
|
type?: FunctionSearchType,
|
||||||
|
paramNames?: string[],
|
||||||
|
displayType: Promise<Array<Array<string>>>|null,
|
||||||
|
displayTypeMappedNames: Promise<Array<[string, Array<string>]>>|null,
|
||||||
|
item: Row,
|
||||||
|
dontValidate?: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pair of [inputs, outputs], or 0 for null. This is stored in the search index.
|
||||||
|
* The JavaScript deserializes this into FunctionSearchType.
|
||||||
|
*
|
||||||
|
* Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null`
|
||||||
|
* because `null` is four bytes while `0` is one byte.
|
||||||
|
*
|
||||||
|
* An input or output can be encoded as just a number if there is only one of them, AND
|
||||||
|
* it has no generics. The no generics rule exists to avoid ambiguity: imagine if you had
|
||||||
|
* a function with a single output, and that output had a single generic:
|
||||||
|
*
|
||||||
|
* fn something() -> Result<usize, usize>
|
||||||
|
*
|
||||||
|
* If output was allowed to be any RawFunctionType, it would look like thi
|
||||||
|
*
|
||||||
|
* [[], [50, [3, 3]]]
|
||||||
|
*
|
||||||
|
* The problem is that the above output could be interpreted as either a type with ID 50 and two
|
||||||
|
* generics, or it could be interpreted as a pair of types, the first one with ID 50 and the second
|
||||||
|
* with ID 3 and a single generic parameter that is also ID 3. We avoid this ambiguity by choosing
|
||||||
|
* in favor of the pair of types interpretation. This is why the `(number|Array<RawFunctionType>)`
|
||||||
|
* is used instead of `(RawFunctionType|Array<RawFunctionType>)`.
|
||||||
|
*
|
||||||
|
* The output can be skipped if it's actually unit and there's no type constraints. If thi
|
||||||
|
* function accepts constrained generics, then the output will be unconditionally emitted, and
|
||||||
|
* after it will come a list of trait constraints. The position of the item in the list will
|
||||||
|
* determine which type parameter it is. For example:
|
||||||
|
*
|
||||||
|
* [1, 2, 3, 4, 5]
|
||||||
|
* ^ ^ ^ ^ ^
|
||||||
|
* | | | | - generic parameter (-3) of trait 5
|
||||||
|
* | | | - generic parameter (-2) of trait 4
|
||||||
|
* | | - generic parameter (-1) of trait 3
|
||||||
|
* | - this function returns a single value (type 2)
|
||||||
|
* - this function takes a single input parameter (type 1)
|
||||||
|
*
|
||||||
|
* Or, for a less contrived version:
|
||||||
|
*
|
||||||
|
* [[[4, -1], 3], [[5, -1]], 11]
|
||||||
|
* -^^^^^^^---- ^^^^^^^ ^^
|
||||||
|
* | | | - generic parameter, roughly `where -1: 11`
|
||||||
|
* | | | since -1 is the type parameter and 11 the trait
|
||||||
|
* | | - function output 5<-1>
|
||||||
|
* | - the overall function signature is something like
|
||||||
|
* | `fn(4<-1>, 3) -> 5<-1> where -1: 11`
|
||||||
|
* - function input, corresponds roughly to 4<-1>
|
||||||
|
* 4 is an index into the `p` array for a type
|
||||||
|
* -1 is the generic parameter, given by 11
|
||||||
|
*
|
||||||
|
* If a generic parameter has multiple trait constraints, it gets wrapped in an array, just like
|
||||||
|
* function inputs and outputs:
|
||||||
|
*
|
||||||
|
* [-1, -1, [4, 3]]
|
||||||
|
* ^^^^^^ where -1: 4 + 3
|
||||||
|
*
|
||||||
|
* If a generic parameter's trait constraint has generic parameters, it gets wrapped in the array
|
||||||
|
* even if only one exists. In other words, the ambiguity of `4<3>` and `4 + 3` is resolved in
|
||||||
|
* favor of `4 + 3`:
|
||||||
|
*
|
||||||
|
* [-1, -1, [[4, 3]]]
|
||||||
|
* ^^^^^^^^ where -1: 4 + 3
|
||||||
|
*
|
||||||
|
* [-1, -1, [5, [4, 3]]]
|
||||||
|
* ^^^^^^^^^^^ where -1: 5, -2: 4 + 3
|
||||||
|
*
|
||||||
|
* If a generic parameter has no trait constraints (like in Rust, the `Sized` constraint i
|
||||||
|
* implied and a fake `?Sized` constraint used to note its absence), it will be filled in with 0.
|
||||||
|
*/
|
||||||
|
type RawFunctionSearchType =
|
||||||
|
0 |
|
||||||
|
[(number|Array<RawFunctionType>)] |
|
||||||
|
[(number|Array<RawFunctionType>), (number|Array<RawFunctionType>)] |
|
||||||
|
Array<(number|Array<RawFunctionType>)>
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single function input or output type. This is either a single path ID, or a pair of
|
||||||
|
* [path ID, generics].
|
||||||
|
*
|
||||||
|
* Numeric IDs are *ONE-indexed* into the paths array (`p`). Zero is used as a sentinel for `null`
|
||||||
|
* because `null` is four bytes while `0` is one byte.
|
||||||
|
*/
|
||||||
|
type RawFunctionType = number | [number, Array<RawFunctionType>];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type signature entry in the decoded search index.
|
||||||
|
* (The "Raw" objects are encoded differently to save space in the JSON).
|
||||||
|
*/
|
||||||
|
interface FunctionSearchType {
|
||||||
|
inputs: Array<FunctionType>,
|
||||||
|
output: Array<FunctionType>,
|
||||||
|
where_clause: Array<Array<FunctionType>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A decoded function type, made from real objects.
|
||||||
|
* `ty` will be negative for generics, positive for types, and 0 for placeholders.
|
||||||
|
*/
|
||||||
|
interface FunctionType {
|
||||||
|
id: null|number,
|
||||||
|
ty: number|null,
|
||||||
|
name?: string,
|
||||||
|
path: string|null,
|
||||||
|
exactPath: string|null,
|
||||||
|
unboxFlag: boolean,
|
||||||
|
generics: Array<FunctionType>,
|
||||||
|
bindings: Map<number, Array<FunctionType>>,
|
||||||
|
};
|
||||||
|
|
||||||
|
interface HighlightedFunctionType extends FunctionType {
|
||||||
|
generics: HighlightedFunctionType[],
|
||||||
|
bindings: Map<number, HighlightedFunctionType[]>,
|
||||||
|
highlighted?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FingerprintableType {
|
||||||
|
id: number|null;
|
||||||
|
generics: FingerprintableType[];
|
||||||
|
bindings: Map<number, FingerprintableType[]>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The raw search data for a given crate. `n`, `t`, `d`, `i`, and `f`
|
||||||
|
* are arrays with the same length. `q`, `a`, and `c` use a sparse
|
||||||
|
* representation for compactness.
|
||||||
|
*
|
||||||
|
* `n[i]` contains the name of an item.
|
||||||
|
*
|
||||||
|
* `t[i]` contains the type of that item
|
||||||
|
* (as a string of characters that represent an offset in `itemTypes`).
|
||||||
|
*
|
||||||
|
* `d[i]` contains the description of that item.
|
||||||
|
*
|
||||||
|
* `q` contains the full paths of the items. For compactness, it is a set of
|
||||||
|
* (index, path) pairs used to create a map. If a given index `i` is
|
||||||
|
* not present, this indicates "same as the last index present".
|
||||||
|
*
|
||||||
|
* `i[i]` contains an item's parent, usually a module. For compactness,
|
||||||
|
* it is a set of indexes into the `p` array.
|
||||||
|
*
|
||||||
|
* `f` contains function signatures, or `0` if the item isn't a function.
|
||||||
|
* More information on how they're encoded can be found in rustc-dev-guide
|
||||||
|
*
|
||||||
|
* Functions are themselves encoded as arrays. The first item is a list of
|
||||||
|
* types representing the function's inputs, and the second list item is a list
|
||||||
|
* of types representing the function's output. Tuples are flattened.
|
||||||
|
* Types are also represented as arrays; the first item is an index into the `p`
|
||||||
|
* array, while the second is a list of types representing any generic parameters.
|
||||||
|
*
|
||||||
|
* b[i] contains an item's impl disambiguator. This is only present if an item
|
||||||
|
* is defined in an impl block and, the impl block's type has more than one associated
|
||||||
|
* item with the same name.
|
||||||
|
*
|
||||||
|
* `a` defines aliases with an Array of pairs: [name, offset], where `offset`
|
||||||
|
* points into the n/t/d/q/i/f arrays.
|
||||||
|
*
|
||||||
|
* `doc` contains the description of the crate.
|
||||||
|
*
|
||||||
|
* `p` is a list of path/type pairs. It is used for parents and function parameters.
|
||||||
|
* The first item is the type, the second is the name, the third is the visible path (if any) and
|
||||||
|
* the fourth is the canonical path used for deduplication (if any).
|
||||||
|
*
|
||||||
|
* `r` is the canonical path used for deduplication of re-exported items.
|
||||||
|
* It is not used for associated items like methods (that's the fourth element
|
||||||
|
* of `p`) but is used for modules items like free functions.
|
||||||
|
*
|
||||||
|
* `c` is an array of item indices that are deprecated.
|
||||||
|
*/
|
||||||
|
type RawSearchIndexCrate = {
|
||||||
|
doc: string,
|
||||||
|
a: Object,
|
||||||
|
n: Array<string>,
|
||||||
|
t: string,
|
||||||
|
D: string,
|
||||||
|
e: string,
|
||||||
|
q: Array<[number, string]>,
|
||||||
|
i: string,
|
||||||
|
f: string,
|
||||||
|
p: Array<[number, string] | [number, string, number] | [number, string, number, number] | [number, string, number, number, string]>,
|
||||||
|
b: Array<[number, String]>,
|
||||||
|
c: string,
|
||||||
|
r: Array<[number, number]>,
|
||||||
|
P: Array<[number, string]>,
|
||||||
|
};
|
||||||
|
|
||||||
|
type VlqData = VlqData[] | number;
|
||||||
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
/* global addClass, hasClass, removeClass, onEachLazy */
|
/* global addClass, hasClass, removeClass, onEachLazy */
|
||||||
|
|
||||||
|
// Eventually fix this.
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,9 @@
|
||||||
/* global addClass, removeClass, onEach, onEachLazy */
|
/* global addClass, removeClass, onEach, onEachLazy */
|
||||||
/* global MAIN_ID, getVar, getSettingsButton, getHelpButton */
|
/* global MAIN_ID, getVar, getSettingsButton, getHelpButton */
|
||||||
|
|
||||||
|
// Eventually fix this.
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
/* global addClass, onEachLazy, removeClass, browserSupportsHistoryApi */
|
/* global addClass, onEachLazy, removeClass, browserSupportsHistoryApi */
|
||||||
/* global updateLocalStorage, getVar */
|
/* global updateLocalStorage, getVar */
|
||||||
|
|
||||||
|
// Eventually fix this.
|
||||||
|
// @ts-nocheck
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
|
@ -5,15 +5,28 @@
|
||||||
// the page, so we don't see major layout changes during the load of the page.
|
// the page, so we don't see major layout changes during the load of the page.
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @import * as rustdoc from "./rustdoc.d.ts";
|
||||||
|
*/
|
||||||
|
|
||||||
const builtinThemes = ["light", "dark", "ayu"];
|
const builtinThemes = ["light", "dark", "ayu"];
|
||||||
const darkThemes = ["dark", "ayu"];
|
const darkThemes = ["dark", "ayu"];
|
||||||
window.currentTheme = document.getElementById("themeStyle");
|
window.currentTheme = (function() {
|
||||||
|
const currentTheme = document.getElementById("themeStyle");
|
||||||
|
return currentTheme instanceof HTMLLinkElement ? currentTheme : null;
|
||||||
|
})();
|
||||||
|
|
||||||
const settingsDataset = (function() {
|
const settingsDataset = (function() {
|
||||||
const settingsElement = document.getElementById("default-settings");
|
const settingsElement = document.getElementById("default-settings");
|
||||||
return settingsElement && settingsElement.dataset ? settingsElement.dataset : null;
|
return settingsElement && settingsElement.dataset ? settingsElement.dataset : null;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a configuration value. If it's not set, get the default.
|
||||||
|
*
|
||||||
|
* @param {string} settingName
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
function getSettingValue(settingName) {
|
function getSettingValue(settingName) {
|
||||||
const current = getCurrentValue(settingName);
|
const current = getCurrentValue(settingName);
|
||||||
if (current === null && settingsDataset !== null) {
|
if (current === null && settingsDataset !== null) {
|
||||||
|
@ -29,17 +42,39 @@ function getSettingValue(settingName) {
|
||||||
|
|
||||||
const localStoredTheme = getSettingValue("theme");
|
const localStoredTheme = getSettingValue("theme");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a DOM Element has the given class set.
|
||||||
|
* If `elem` is null, returns false.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement|null} elem
|
||||||
|
* @param {string} className
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
function hasClass(elem, className) {
|
function hasClass(elem, className) {
|
||||||
return elem && elem.classList && elem.classList.contains(className);
|
return !!elem && !!elem.classList && elem.classList.contains(className);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a class to a DOM Element. If `elem` is null,
|
||||||
|
* does nothing. This function is idempotent.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement|null} elem
|
||||||
|
* @param {string} className
|
||||||
|
*/
|
||||||
function addClass(elem, className) {
|
function addClass(elem, className) {
|
||||||
if (elem && elem.classList) {
|
if (elem && elem.classList) {
|
||||||
elem.classList.add(className);
|
elem.classList.add(className);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a class from a DOM Element. If `elem` is null,
|
||||||
|
* does nothing. This function is idempotent.
|
||||||
|
*
|
||||||
|
* @param {HTMLElement|null} elem
|
||||||
|
* @param {string} className
|
||||||
|
*/
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
function removeClass(elem, className) {
|
function removeClass(elem, className) {
|
||||||
if (elem && elem.classList) {
|
if (elem && elem.classList) {
|
||||||
|
@ -49,8 +84,8 @@ function removeClass(elem, className) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run a callback for every element of an Array.
|
* Run a callback for every element of an Array.
|
||||||
* @param {Array<?>} arr - The array to iterate over
|
* @param {Array<?>} arr - The array to iterate over
|
||||||
* @param {function(?)} func - The callback
|
* @param {function(?): boolean|undefined} func - The callback
|
||||||
*/
|
*/
|
||||||
function onEach(arr, func) {
|
function onEach(arr, func) {
|
||||||
for (const elem of arr) {
|
for (const elem of arr) {
|
||||||
|
@ -67,8 +102,8 @@ function onEach(arr, func) {
|
||||||
* or a "live" NodeList while modifying it can be very slow.
|
* or a "live" NodeList while modifying it can be very slow.
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
|
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
|
||||||
* https://developer.mozilla.org/en-US/docs/Web/API/NodeList
|
* https://developer.mozilla.org/en-US/docs/Web/API/NodeList
|
||||||
* @param {NodeList<?>|HTMLCollection<?>} lazyArray - An array to iterate over
|
* @param {NodeList|HTMLCollection} lazyArray - An array to iterate over
|
||||||
* @param {function(?)} func - The callback
|
* @param {function(?): boolean} func - The callback
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
function onEachLazy(lazyArray, func) {
|
function onEachLazy(lazyArray, func) {
|
||||||
|
@ -77,6 +112,15 @@ function onEachLazy(lazyArray, func) {
|
||||||
func);
|
func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a configuration value. This uses localstorage,
|
||||||
|
* with a `rustdoc-` prefix, to avoid clashing with other
|
||||||
|
* web apps that may be running in the same domain (for example, mdBook).
|
||||||
|
* If localStorage is disabled, this function does nothing.
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @param {string} value
|
||||||
|
*/
|
||||||
function updateLocalStorage(name, value) {
|
function updateLocalStorage(name, value) {
|
||||||
try {
|
try {
|
||||||
window.localStorage.setItem("rustdoc-" + name, value);
|
window.localStorage.setItem("rustdoc-" + name, value);
|
||||||
|
@ -85,6 +129,15 @@ function updateLocalStorage(name, value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a configuration value. If localStorage is disabled,
|
||||||
|
* this function returns null. If the setting was never
|
||||||
|
* changed by the user, it also returns null; if you want to
|
||||||
|
* be able to use a default value, call `getSettingValue` instead.
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @returns {string|null}
|
||||||
|
*/
|
||||||
function getCurrentValue(name) {
|
function getCurrentValue(name) {
|
||||||
try {
|
try {
|
||||||
return window.localStorage.getItem("rustdoc-" + name);
|
return window.localStorage.getItem("rustdoc-" + name);
|
||||||
|
@ -93,19 +146,29 @@ function getCurrentValue(name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a value from the rustdoc-vars div, which is used to convey data from
|
/**
|
||||||
// Rust to the JS. If there is no such element, return null.
|
* Get a value from the rustdoc-vars div, which is used to convey data from
|
||||||
const getVar = (function getVar(name) {
|
* Rust to the JS. If there is no such element, return null.
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* @returns {string|null}
|
||||||
|
*/
|
||||||
|
function getVar(name) {
|
||||||
const el = document.querySelector("head > meta[name='rustdoc-vars']");
|
const el = document.querySelector("head > meta[name='rustdoc-vars']");
|
||||||
return el ? el.attributes["data-" + name].value : null;
|
return el ? el.getAttribute("data-" + name) : null;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the current theme.
|
||||||
|
* @param {string|null} newThemeName
|
||||||
|
* @param {boolean} saveTheme
|
||||||
|
*/
|
||||||
function switchTheme(newThemeName, saveTheme) {
|
function switchTheme(newThemeName, saveTheme) {
|
||||||
const themeNames = getVar("themes").split(",").filter(t => t);
|
const themeNames = (getVar("themes") || "").split(",").filter(t => t);
|
||||||
themeNames.push(...builtinThemes);
|
themeNames.push(...builtinThemes);
|
||||||
|
|
||||||
// Ensure that the new theme name is among the defined themes
|
// Ensure that the new theme name is among the defined themes
|
||||||
if (themeNames.indexOf(newThemeName) === -1) {
|
if (newThemeName === null || themeNames.indexOf(newThemeName) === -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +181,7 @@ function switchTheme(newThemeName, saveTheme) {
|
||||||
document.documentElement.setAttribute("data-theme", newThemeName);
|
document.documentElement.setAttribute("data-theme", newThemeName);
|
||||||
|
|
||||||
if (builtinThemes.indexOf(newThemeName) !== -1) {
|
if (builtinThemes.indexOf(newThemeName) !== -1) {
|
||||||
if (window.currentTheme) {
|
if (window.currentTheme && window.currentTheme.parentNode) {
|
||||||
window.currentTheme.parentNode.removeChild(window.currentTheme);
|
window.currentTheme.parentNode.removeChild(window.currentTheme);
|
||||||
window.currentTheme = null;
|
window.currentTheme = null;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +193,10 @@ function switchTheme(newThemeName, saveTheme) {
|
||||||
// rendering, but if we are done, it would blank the page.
|
// rendering, but if we are done, it would blank the page.
|
||||||
if (document.readyState === "loading") {
|
if (document.readyState === "loading") {
|
||||||
document.write(`<link rel="stylesheet" id="themeStyle" href="${newHref}">`);
|
document.write(`<link rel="stylesheet" id="themeStyle" href="${newHref}">`);
|
||||||
window.currentTheme = document.getElementById("themeStyle");
|
window.currentTheme = (function() {
|
||||||
|
const currentTheme = document.getElementById("themeStyle");
|
||||||
|
return currentTheme instanceof HTMLLinkElement ? currentTheme : null;
|
||||||
|
})();
|
||||||
} else {
|
} else {
|
||||||
window.currentTheme = document.createElement("link");
|
window.currentTheme = document.createElement("link");
|
||||||
window.currentTheme.rel = "stylesheet";
|
window.currentTheme.rel = "stylesheet";
|
||||||
|
@ -179,11 +245,13 @@ const updateTheme = (function() {
|
||||||
return updateTheme;
|
return updateTheme;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
|
if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
|
||||||
// update the preferred dark theme if the user is already using a dark theme
|
// update the preferred dark theme if the user is already using a dark theme
|
||||||
// See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
|
// See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
|
||||||
if (getSettingValue("use-system-theme") === null
|
if (getSettingValue("use-system-theme") === null
|
||||||
&& getSettingValue("preferred-dark-theme") === null
|
&& getSettingValue("preferred-dark-theme") === null
|
||||||
|
&& localStoredTheme !== null
|
||||||
&& darkThemes.indexOf(localStoredTheme) >= 0) {
|
&& darkThemes.indexOf(localStoredTheme) >= 0) {
|
||||||
updateLocalStorage("preferred-dark-theme", localStoredTheme);
|
updateLocalStorage("preferred-dark-theme", localStoredTheme);
|
||||||
}
|
}
|
||||||
|
|
15
src/librustdoc/html/static/js/tsconfig.json
Normal file
15
src/librustdoc/html/static/js/tsconfig.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2023",
|
||||||
|
"module": "esnext",
|
||||||
|
"rootDir": "./",
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"typeAcquisition": {
|
||||||
|
"include": ["./rustdoc.d.ts"]
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue