From 4f9fe856a25ab29345b90e7725509e9ee38a37be Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:41 +0200 Subject: Adding upstream version 1.69.0+dfsg1. Signed-off-by: Daniel Baumann --- src/librustdoc/html/static/.eslintrc.js | 1 - src/librustdoc/html/static/css/rustdoc.css | 148 +++++---- src/librustdoc/html/static/css/settings.css | 30 +- src/librustdoc/html/static/css/themes/ayu.css | 77 ++--- src/librustdoc/html/static/css/themes/dark.css | 26 +- src/librustdoc/html/static/css/themes/light.css | 26 +- .../html/static/fonts/SourceSerif4-Bold.ttf.woff2 | Bin 81320 -> 81540 bytes .../html/static/fonts/SourceSerif4-It.ttf.woff2 | Bin 59860 -> 59716 bytes .../html/static/fonts/SourceSerif4-LICENSE.md | 2 +- .../static/fonts/SourceSerif4-Regular.ttf.woff2 | Bin 76180 -> 76260 bytes src/librustdoc/html/static/images/down-arrow.svg | 1 - src/librustdoc/html/static/images/toggle-minus.svg | 1 - src/librustdoc/html/static/images/toggle-plus.svg | 1 - src/librustdoc/html/static/images/wheel.svg | 2 +- src/librustdoc/html/static/js/main.js | 125 ++++---- src/librustdoc/html/static/js/search.js | 355 +++++++++++++-------- src/librustdoc/html/static/js/settings.js | 55 ++-- src/librustdoc/html/static/js/source-script.js | 3 +- src/librustdoc/html/static/js/storage.js | 113 +++---- 19 files changed, 496 insertions(+), 470 deletions(-) delete mode 100644 src/librustdoc/html/static/images/down-arrow.svg delete mode 100644 src/librustdoc/html/static/images/toggle-minus.svg delete mode 100644 src/librustdoc/html/static/images/toggle-plus.svg (limited to 'src/librustdoc/html/static') diff --git a/src/librustdoc/html/static/.eslintrc.js b/src/librustdoc/html/static/.eslintrc.js index fcd925bb3..1a34530c2 100644 --- a/src/librustdoc/html/static/.eslintrc.js +++ b/src/librustdoc/html/static/.eslintrc.js @@ -90,7 +90,6 @@ module.exports = { "no-return-assign": "error", "no-script-url": "error", "no-sequences": "error", - "no-throw-literal": "error", "no-div-regex": "error", } }; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index a93f60da2..95528e70e 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1,3 +1,11 @@ +/* When static files are updated, their suffixes need to be updated. + 1. In the top directory run: + ./x.py doc --stage 1 library/core + 2. Find the directory containing files named with updated suffixes: + find build -path '*'/stage1-std/'*'/static.files + 3. Copy the filenames with updated suffixes from the directory. +*/ + /* See FiraSans-LICENSE.txt for the Fira Sans license. */ @font-face { font-family: 'Fira Sans'; @@ -22,7 +30,7 @@ font-style: normal; font-weight: 400; src: local('Source Serif 4'), - url("SourceSerif4-Regular-1f7d512b176f0f72.ttf.woff2") format("woff2"); + url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2"); font-display: swap; } @font-face { @@ -30,7 +38,7 @@ font-style: italic; font-weight: 400; src: local('Source Serif 4 Italic'), - url("SourceSerif4-It-d034fe4ef9d0fa00.ttf.woff2") format("woff2"); + url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2"); font-display: swap; } @font-face { @@ -38,7 +46,7 @@ font-style: normal; font-weight: 700; src: local('Source Serif 4 Bold'), - url("SourceSerif4-Bold-124a1ca42af929b6.ttf.woff2") format("woff2"); + url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2"); font-display: swap; } @@ -166,6 +174,14 @@ h1, h2, h3, h4 { .top-doc .docblock > h4 { border-bottom: 1px solid var(--headings-border-bottom-color); } +/* while line-height 1.5 is required for any "block of text", + which WCAG defines as more than one sentence, it looks weird for + very large main headers */ +h1, h2 { + line-height: 1.25; + padding-top: 3px; + padding-bottom: 9px; +} h3.code-header { font-size: 1.125rem; /* 18px */ } @@ -176,6 +192,7 @@ h4.code-header { font-weight: 600; margin: 0; padding: 0; + white-space: pre-wrap; } #crate-search, @@ -184,7 +201,7 @@ h1, h2, h3, h4, h5, h6, .mobile-topbar, .search-input, .search-results .result-name, -.item-left > a, +.item-name > a, .out-of-band, span.since, a.srclink, @@ -335,7 +352,7 @@ pre { padding: 14px; line-height: 1.5; /* https://github.com/rust-lang/rust/issues/105906 */ } -.item-decl pre { +pre.item-decl { overflow-x: auto; } /* This rule allows to have scrolling on the X axis. */ @@ -533,7 +550,7 @@ ul.block, .block li { .rustdoc .example-wrap > pre { margin: 0; flex-grow: 1; - overflow-x: auto; + overflow: auto hidden; } .rustdoc .example-wrap > pre.example-line-numbers, @@ -634,6 +651,7 @@ pre, .rustdoc.source .example-wrap { .fn .where, .where.fmt-newline { display: block; + white-space: pre-wrap; font-size: 0.875rem; } @@ -697,8 +715,8 @@ h2.small-section-header > .anchor { .main-heading a:hover, .example-wrap > pre.rust a:hover, .all-items a:hover, -.docblock a:not(.test-arrow):not(.scrape-help):hover, -.docblock-short a:not(.test-arrow):not(.scrape-help):hover, +.docblock a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover, +.docblock-short a:not(.test-arrow):not(.scrape-help):not(.tooltip):hover, .item-info a { text-decoration: underline; } @@ -732,14 +750,16 @@ table, .item-table { display: table; + padding: 0; + margin: 0; } -.item-row { +.item-table > li { display: table-row; } -.item-left, .item-right { +.item-table > li > div { display: table-cell; } -.item-left { +.item-table > li > .item-name { padding-right: 1.25rem; } @@ -806,8 +826,11 @@ so that we can apply CSS-filters to change the arrow color in themes */ background-repeat: no-repeat; background-size: 20px; background-position: calc(100% - 2px) 56%; - /* image is black color */ - background-image: url("down-arrow-927217e04c7463ac.svg"); + /* down arrow (image is black color) */ + background-image: url('data:image/svg+xml, \ + '); /* changes the arrow image color */ filter: var(--crate-search-div-filter); } @@ -941,7 +964,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ padding: 3px; margin-bottom: 5px; } -.item-left .stab { +.item-name .stab { margin-left: 0.3125em; } .stab { @@ -977,11 +1000,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ 0 -1px 0 black; } -.module-item.unstable, -.import-item.unstable { - opacity: 0.65; -} - .since { font-weight: normal; font-size: initial; @@ -1093,44 +1111,8 @@ pre.rust .doccomment { display: block; left: -25px; top: 5px; -} - -.example-wrap .tooltip:hover::after { - padding: 5px 3px 3px 3px; - border-radius: 6px; - margin-left: 5px; - font-size: 1rem; - border: 1px solid var(--border-color); - position: absolute; - width: max-content; - top: -2px; - z-index: 1; - background-color: var(--tooltip-background-color); - color: var(--tooltip-color); -} - -.example-wrap .tooltip:hover::before { - content: " "; - position: absolute; - top: 50%; - left: 16px; - margin-top: -5px; - z-index: 1; - border: 5px solid transparent; - border-right-color: var(--tooltip-background-color); -} - -.example-wrap.ignore .tooltip:hover::after { - content: "This example is not tested"; -} -.example-wrap.compile_fail .tooltip:hover::after { - content: "This example deliberately fails to compile"; -} -.example-wrap.should_panic .tooltip:hover::after { - content: "This example panics"; -} -.example-wrap.edition .tooltip:hover::after { - content: "This code runs with edition " attr(data-edition); + margin: 0; + line-height: 1; } .example-wrap.compile_fail .tooltip, @@ -1168,6 +1150,7 @@ a.test-arrow:hover { .item-spacer { width: 100%; height: 12px; + display: block; } .out-of-band > span.since { @@ -1196,7 +1179,7 @@ a.test-arrow:hover { border-right: 3px solid var(--target-border-color); } -.notable-traits { +.code-header a.tooltip { color: inherit; margin-right: 15px; position: relative; @@ -1205,7 +1188,7 @@ a.test-arrow:hover { /* placeholder thunk so that the mouse can easily travel from "(i)" to popover the resulting "hover tunnel" is a stepped triangle, approximating https://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown */ -.notable-traits:hover::after { +a.tooltip:hover::after { position: absolute; top: calc(100% - 10px); left: -15px; @@ -1214,11 +1197,11 @@ a.test-arrow:hover { content: "\00a0"; } -.notable .content { +.popover.tooltip .content { margin: 0.25em 0.5em; } -.notable .content pre, .notable .content code { +.popover.tooltip .content pre, .popover.tooltip .content code { background: transparent; margin: 0; padding: 0; @@ -1226,7 +1209,7 @@ a.test-arrow:hover { white-space: pre-wrap; } -.notable .content > h3:first-child { +.popover.tooltip .content > h3:first-child { margin: 0 0 5px 0; } @@ -1263,12 +1246,25 @@ a.test-arrow:hover { line-height: 1.5; color: inherit; } +#search-tabs button:not(.selected) { + background-color: var(--search-tab-button-not-selected-background); + border-top-color: var(--search-tab-button-not-selected-border-top-color); +} +#search-tabs button:hover, #search-tabs button.selected { + background-color: var(--search-tab-button-selected-background); + border-top-color: var(--search-tab-button-selected-border-top-color); +} #search-tabs .count { font-size: 1rem; color: var(--search-tab-title-count-color); } +#search .error code { + border-radius: 3px; + background-color: var(--search-error-code-background-color); +} + #src-sidebar-toggle { position: sticky; top: 0; @@ -1433,7 +1429,10 @@ details.toggle > summary.hideme > span { } details.toggle > summary::before { - background: url("toggle-plus-1092eb4930d581b0.svg") no-repeat top left; + /* toggle plus */ + background: url('data:image/svg+xml,') no-repeat top left; content: ""; cursor: pointer; width: 16px; @@ -1511,7 +1510,10 @@ details.toggle[open] > summary.hideme > span { } details.toggle[open] > summary::before { - background: url("toggle-minus-31bbd6e4c77f5c96.svg") no-repeat top left; + /* toggle minus */ + background: url('data:image/svg+xml,') no-repeat top left; } details.toggle[open] > summary::after { @@ -1700,7 +1702,7 @@ in storage.js } /* Display an alternating layout on tablets and phones */ - .item-table, .item-row, .item-left, .item-right, + .item-table, .item-row, .item-table > li, .item-table > li > div, .search-results > a, .search-results > a > div { display: block; } @@ -1709,7 +1711,7 @@ in storage.js .search-results > a { padding: 5px 0px; } - .search-results > a > div.desc, .item-right { + .search-results > a > div.desc, .item-table > li > div.desc { padding-left: 2em; } @@ -1897,19 +1899,25 @@ in storage.js right: 0.25em; } -.scraped-example:not(.expanded) .code-wrapper:before, -.scraped-example:not(.expanded) .code-wrapper:after { +.scraped-example:not(.expanded) .code-wrapper::before, +.scraped-example:not(.expanded) .code-wrapper::after { content: " "; width: 100%; height: 5px; position: absolute; z-index: 1; } -.scraped-example:not(.expanded) .code-wrapper:before { +.scraped-example:not(.expanded) .code-wrapper::before { top: 0; + background: linear-gradient(to bottom, + var(--scrape-example-code-wrapper-background-start), + var(--scrape-example-code-wrapper-background-end)); } -.scraped-example:not(.expanded) .code-wrapper:after { +.scraped-example:not(.expanded) .code-wrapper::after { bottom: 0; + background: linear-gradient(to top, + var(--scrape-example-code-wrapper-background-start), + var(--scrape-example-code-wrapper-background-end)); } .scraped-example .code-wrapper .example-wrap { diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css index 4e9803fe2..920f45c4b 100644 --- a/src/librustdoc/html/static/css/settings.css +++ b/src/librustdoc/html/static/css/settings.css @@ -3,8 +3,7 @@ position: relative; } -.setting-line .radio-line input, -.setting-line .settings-toggle input { +.setting-radio input, .setting-check input { margin-right: 0.3em; height: 1.2rem; width: 1.2rem; @@ -14,21 +13,20 @@ -webkit-appearance: none; cursor: pointer; } -.setting-line .radio-line input { +.setting-radio input { border-radius: 50%; } -.setting-line .settings-toggle input:checked { +.setting-check input:checked { content: url('data:image/svg+xml,\ \ '); } -.setting-line .radio-line input + span, -.setting-line .settings-toggle span { +.setting-radio span, .setting-check span { padding-bottom: 1px; } -.radio-line .choice { +.setting-radio { margin-top: 0.1em; margin-bottom: 0.1em; min-width: 3.8em; @@ -37,36 +35,32 @@ align-items: center; cursor: pointer; } -.radio-line .choice + .choice { +.setting-radio + .setting-radio { margin-left: 0.5em; } -.settings-toggle { - position: relative; - width: 100%; +.setting-check { margin-right: 20px; display: flex; align-items: center; cursor: pointer; } -.setting-line .radio-line input:checked { +.setting-radio input:checked { box-shadow: inset 0 0 0 3px var(--main-background-color); background-color: var(--settings-input-color); } -.setting-line .settings-toggle input:checked { +.setting-check input:checked { background-color: var(--settings-input-color); } -.setting-line .radio-line input:focus, -.setting-line .settings-toggle input:focus { +.setting-radio input:focus, .setting-check input:focus { box-shadow: 0 0 1px 1px var(--settings-input-color); } /* In here we combine both `:focus` and `:checked` properties. */ -.setting-line .radio-line input:checked:focus { +.setting-radio input:checked:focus { box-shadow: inset 0 0 0 3px var(--main-background-color), 0 0 2px 2px var(--settings-input-color); } -.setting-line .radio-line input:hover, -.setting-line .settings-toggle input:hover { +.setting-radio input:hover, .setting-check input:hover { border-color: var(--settings-input-color) !important; } diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 979e7e0f9..90cf689ad 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -43,9 +43,14 @@ Original by Dempfi (https://github.com/dempfi/ayu) --search-result-link-focus-background-color: #3c3c3c; --search-result-border-color: #aaa3; --search-color: #fff; + --search-error-code-background-color: #4f4c4c; --search-results-alias-color: #c5c5c5; --search-results-grey-color: #999; --search-tab-title-count-color: #888; + --search-tab-button-not-selected-border-top-color: none; + --search-tab-button-not-selected-background: transparent !important; + --search-tab-button-selected-border-top-color: none; + --search-tab-button-selected-background: #141920 !important; --stab-background-color: #314559; --stab-code-color: #e6e1cf; --code-highlight-kw-color: #ff7733; @@ -70,8 +75,6 @@ Original by Dempfi (https://github.com/dempfi/ayu) --test-arrow-hover-background-color: rgba(57, 175, 215, 0.368); --target-background-color: rgba(255, 236, 164, 0.06); --target-border-color: rgba(255, 180, 76, 0.85); - --tooltip-background-color: #314559; - --tooltip-color: #c5c5c5; --kbd-color: #c5c5c5; --kbd-background: #314559; --kbd-box-shadow-color: #5c6773; @@ -97,12 +100,13 @@ Original by Dempfi (https://github.com/dempfi/ayu) --scrape-example-help-color: #eee; --scrape-example-help-hover-border-color: #fff; --scrape-example-help-hover-color: #fff; + --scrape-example-code-wrapper-background-start: rgba(15, 20, 25, 1); + --scrape-example-code-wrapper-background-end: rgba(15, 20, 25, 0); } -h1, h2, h3, h4 { - color: white; -} -h1 a { +h1, h2, h3, h4, +h1 a, .sidebar h2 a, .sidebar h3 a, +#source-sidebar > .title { color: #fff; } h4 { @@ -112,24 +116,22 @@ h4 { .docblock code { color: #ffb454; } -.code-header { - color: #e6e1cf; -} -.docblock pre > code, pre > code { - color: #e6e1cf; -} -.item-info code { - color: #e6e1cf; -} .docblock a > code { color: #39AFD7 !important; } -pre, .rustdoc.source .example-wrap { +.code-header, +.docblock pre > code, +pre, pre > code, +.item-info code, +.rustdoc.source .example-wrap { color: #e6e1cf; } .sidebar .current, -.sidebar a:hover { +.sidebar a:hover, +#source-sidebar div.files > a:hover, details.dir-entry summary:hover, +#source-sidebar div.files > a:focus, details.dir-entry summary:focus, +#source-sidebar div.files > a.selected { color: #ffb44c; } @@ -143,15 +145,12 @@ pre, .rustdoc.source .example-wrap { border-right: 1px solid #ffb44c; } -.search-results a:hover { - color: #fff !important; - background-color: #3c3c3c; -} - +.search-results a:hover, .search-results a:focus { color: #fff !important; background-color: #3c3c3c; } + .search-results a { color: #0096cf; } @@ -159,54 +158,22 @@ pre, .rustdoc.source .example-wrap { color: #c5c5c5; } -.sidebar h2 a, -.sidebar h3 a { - color: white; -} - .result-name .primitive > i, .result-name .keyword > i { color: #788797; } #search-tabs > button.selected { - background-color: #141920 !important; border-bottom: 1px solid #ffb44c !important; border-top: none; } - #search-tabs > button:not(.selected) { - background-color: transparent !important; border: none; + background-color: transparent !important; } - #search-tabs > button:hover { border-bottom: 1px solid rgba(242, 151, 24, 0.3); } -/* rules that this theme does not need to set, here to satisfy the rule checker */ -/* note that a lot of these are partially set in some way (meaning they are set -individually rather than as a group) */ -/* FIXME: these rules should be at the bottom of the file but currently must be -above the `@media (max-width: 700px)` rules due to a bug in the css checker */ -/* see https://github.com/rust-lang/rust/pull/71237#issuecomment-618170143 */ -#search-tabs > button:hover, #search-tabs > button.selected {} - #settings-menu > a img { filter: invert(100); } - -#source-sidebar > .title { - color: #fff; -} -#source-sidebar div.files > a:hover, details.dir-entry summary:hover, -#source-sidebar div.files > a:focus, details.dir-entry summary:focus, -#source-sidebar div.files > a.selected { - color: #ffb44c; -} - -.scraped-example:not(.expanded) .code-wrapper::before { - background: linear-gradient(to bottom, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0)); -} -.scraped-example:not(.expanded) .code-wrapper::after { - background: linear-gradient(to top, rgba(15, 20, 25, 1), rgba(15, 20, 25, 0)); -} diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index fb15863b0..e8cd06931 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -38,9 +38,14 @@ --search-result-link-focus-background-color: #616161; --search-result-border-color: #aaa3; --search-color: #111; + --search-error-code-background-color: #484848; --search-results-alias-color: #fff; --search-results-grey-color: #ccc; --search-tab-title-count-color: #888; + --search-tab-button-not-selected-border-top-color: #252525; + --search-tab-button-not-selected-background: #252525; + --search-tab-button-selected-border-top-color: #0089ff; + --search-tab-button-selected-background: #353535; --stab-background-color: #314559; --stab-code-color: #e6e1cf; --code-highlight-kw-color: #ab8ac1; @@ -65,8 +70,6 @@ --test-arrow-hover-background-color: #4e8bca; --target-background-color: #494a3d; --target-border-color: #bb7410; - --tooltip-background-color: #000; - --tooltip-color: #fff; --kbd-color: #000; --kbd-background: #fafbfc; --kbd-box-shadow-color: #c6cbd1; @@ -92,21 +95,6 @@ --scrape-example-help-color: #eee; --scrape-example-help-hover-border-color: #fff; --scrape-example-help-hover-color: #fff; -} - -#search-tabs > button:not(.selected) { - background-color: #252525; - border-top-color: #252525; -} - -#search-tabs > button:hover, #search-tabs > button.selected { - border-top-color: #0089ff; - background-color: #353535; -} - -.scraped-example:not(.expanded) .code-wrapper::before { - background: linear-gradient(to bottom, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0)); -} -.scraped-example:not(.expanded) .code-wrapper::after { - background: linear-gradient(to top, rgba(53, 53, 53, 1), rgba(53, 53, 53, 0)); + --scrape-example-code-wrapper-background-start: rgba(53, 53, 53, 1); + --scrape-example-code-wrapper-background-end: rgba(53, 53, 53, 0); } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 053fa78d1..5e3f14e48 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -38,9 +38,14 @@ --search-result-link-focus-background-color: #ccc; --search-result-border-color: #aaa3; --search-color: #000; + --search-error-code-background-color: #d0cccc; --search-results-alias-color: #000; --search-results-grey-color: #999; --search-tab-title-count-color: #888; + --search-tab-button-not-selected-border-top-color: #e6e6e6; + --search-tab-button-not-selected-background: #e6e6e6; + --search-tab-button-selected-border-top-color: #0089ff; + --search-tab-button-selected-background: #ffffff; --stab-background-color: #fff5d6; --stab-code-color: #000; --code-highlight-kw-color: #8959a8; @@ -65,8 +70,6 @@ --test-arrow-hover-background-color: #4e8bca; --target-background-color: #fdffd3; --target-border-color: #ad7c37; - --tooltip-background-color: #000; - --tooltip-color: #fff; --kbd-color: #000; --kbd-background: #fafbfc; --kbd-box-shadow-color: #c6cbd1; @@ -89,21 +92,6 @@ --scrape-example-help-color: #333; --scrape-example-help-hover-border-color: #000; --scrape-example-help-hover-color: #000; -} - -#search-tabs > button:not(.selected) { - background-color: #e6e6e6; - border-top-color: #e6e6e6; -} - -#search-tabs > button:hover, #search-tabs > button.selected { - background-color: #ffffff; - border-top-color: #0089ff; -} - -.scraped-example:not(.expanded) .code-wrapper::before { - background: linear-gradient(to bottom, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); -} -.scraped-example:not(.expanded) .code-wrapper::after { - background: linear-gradient(to top, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0)); + --scrape-example-code-wrapper-background-start: rgba(255, 255, 255, 1); + --scrape-example-code-wrapper-background-end: rgba(255, 255, 255, 0); } diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 index db57d2145..181a07f63 100644 Binary files a/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 and b/src/librustdoc/html/static/fonts/SourceSerif4-Bold.ttf.woff2 differ diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 index 1cbc021a3..2ae08a7be 100644 Binary files a/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 and b/src/librustdoc/html/static/fonts/SourceSerif4-It.ttf.woff2 differ diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md b/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md index 68ea18924..5871e1f3d 100644 --- a/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md +++ b/src/librustdoc/html/static/fonts/SourceSerif4-LICENSE.md @@ -1,4 +1,4 @@ -Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. +Copyright 2014 - 2023 Adobe (http://www.adobe.com/), with Reserved Font Name ‘Source’. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. This Font Software is licensed under the SIL Open Font License, Version 1.1. diff --git a/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 b/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 index 2db73fe2b..0263fc304 100644 Binary files a/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 and b/src/librustdoc/html/static/fonts/SourceSerif4-Regular.ttf.woff2 differ diff --git a/src/librustdoc/html/static/images/down-arrow.svg b/src/librustdoc/html/static/images/down-arrow.svg deleted file mode 100644 index 5d76a64e9..000000000 --- a/src/librustdoc/html/static/images/down-arrow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/librustdoc/html/static/images/toggle-minus.svg b/src/librustdoc/html/static/images/toggle-minus.svg deleted file mode 100644 index 73154788a..000000000 --- a/src/librustdoc/html/static/images/toggle-minus.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/librustdoc/html/static/images/toggle-plus.svg b/src/librustdoc/html/static/images/toggle-plus.svg deleted file mode 100644 index 08b17033e..000000000 --- a/src/librustdoc/html/static/images/toggle-plus.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/librustdoc/html/static/images/wheel.svg b/src/librustdoc/html/static/images/wheel.svg index 01da3b24c..83c07f63d 100644 --- a/src/librustdoc/html/static/images/wheel.svg +++ b/src/librustdoc/html/static/images/wheel.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 604ab147f..5e8c0e8d1 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -180,7 +180,6 @@ function browserSupportsHistoryApi() { return window.history && typeof window.history.pushState === "function"; } -// eslint-disable-next-line no-unused-vars function loadCss(cssUrl) { const link = document.createElement("link"); link.href = cssUrl; @@ -379,7 +378,7 @@ function loadCss(cssUrl) { } ev.preventDefault(); searchState.defocus(); - window.hideAllModals(true); // true = reset focus for notable traits + window.hideAllModals(true); // true = reset focus for tooltips } function handleShortcut(ev) { @@ -456,10 +455,7 @@ function loadCss(cssUrl) { const ul = document.createElement("ul"); ul.className = "block " + shortty; - for (const item of filtered) { - const name = item[0]; - const desc = item[1]; // can be null - + for (const name of filtered) { let path; if (shortty === "mod") { path = name + "/index.html"; @@ -469,7 +465,6 @@ function loadCss(cssUrl) { const current_page = document.location.href.split("/").pop(); const link = document.createElement("a"); link.href = path; - link.title = desc; if (path === current_page) { link.className = "current"; } @@ -789,17 +784,17 @@ function loadCss(cssUrl) { // we need to switch away from mobile mode and make the main content area scrollable. hideSidebar(); } - if (window.CURRENT_NOTABLE_ELEMENT) { - // As a workaround to the behavior of `contains: layout` used in doc togglers, the - // notable traits popup is positioned using javascript. + if (window.CURRENT_TOOLTIP_ELEMENT) { + // As a workaround to the behavior of `contains: layout` used in doc togglers, + // tooltip popovers are positioned using javascript. // // This means when the window is resized, we need to redo the layout. - const base = window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE; - const force_visible = base.NOTABLE_FORCE_VISIBLE; - hideNotable(false); + const base = window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE; + const force_visible = base.TOOLTIP_FORCE_VISIBLE; + hideTooltip(false); if (force_visible) { - showNotable(base); - base.NOTABLE_FORCE_VISIBLE = true; + showTooltip(base); + base.TOOLTIP_FORCE_VISIBLE = true; } } }); @@ -827,27 +822,35 @@ function loadCss(cssUrl) { }); }); - function showNotable(e) { - if (!window.NOTABLE_TRAITS) { + function showTooltip(e) { + const notable_ty = e.getAttribute("data-notable-ty"); + if (!window.NOTABLE_TRAITS && notable_ty) { const data = document.getElementById("notable-traits-data"); if (data) { window.NOTABLE_TRAITS = JSON.parse(data.innerText); } else { - throw new Error("showNotable() called on page without any notable traits!"); + throw new Error("showTooltip() called with notable without any notable traits!"); } } - if (window.CURRENT_NOTABLE_ELEMENT && window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE === e) { + if (window.CURRENT_TOOLTIP_ELEMENT && window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE === e) { // Make this function idempotent. return; } window.hideAllModals(false); - const ty = e.getAttribute("data-ty"); const wrapper = document.createElement("div"); - wrapper.innerHTML = "
" + window.NOTABLE_TRAITS[ty] + "
"; - wrapper.className = "notable popover"; + if (notable_ty) { + wrapper.innerHTML = "
" + + window.NOTABLE_TRAITS[notable_ty] + "
"; + } else if (e.getAttribute("title") !== undefined) { + const titleContent = document.createElement("div"); + titleContent.className = "content"; + titleContent.appendChild(document.createTextNode(e.getAttribute("title"))); + wrapper.appendChild(titleContent); + } + wrapper.className = "tooltip popover"; const focusCatcher = document.createElement("div"); focusCatcher.setAttribute("tabindex", "0"); - focusCatcher.onfocus = hideNotable; + focusCatcher.onfocus = hideTooltip; wrapper.appendChild(focusCatcher); const pos = e.getBoundingClientRect(); // 5px overlap so that the mouse can easily travel from place to place @@ -869,62 +872,62 @@ function loadCss(cssUrl) { ); } wrapper.style.visibility = ""; - window.CURRENT_NOTABLE_ELEMENT = wrapper; - window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE = e; + window.CURRENT_TOOLTIP_ELEMENT = wrapper; + window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE = e; wrapper.onpointerleave = function(ev) { // If this is a synthetic touch event, ignore it. A click event will be along shortly. if (ev.pointerType !== "mouse") { return; } - if (!e.NOTABLE_FORCE_VISIBLE && !elemIsInParent(event.relatedTarget, e)) { - hideNotable(true); + if (!e.TOOLTIP_FORCE_VISIBLE && !elemIsInParent(event.relatedTarget, e)) { + hideTooltip(true); } }; } - function notableBlurHandler(event) { - if (window.CURRENT_NOTABLE_ELEMENT && - !elemIsInParent(document.activeElement, window.CURRENT_NOTABLE_ELEMENT) && - !elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT) && - !elemIsInParent(document.activeElement, window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE) && - !elemIsInParent(event.relatedTarget, window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE) + function tooltipBlurHandler(event) { + if (window.CURRENT_TOOLTIP_ELEMENT && + !elemIsInParent(document.activeElement, window.CURRENT_TOOLTIP_ELEMENT) && + !elemIsInParent(event.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT) && + !elemIsInParent(document.activeElement, window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE) && + !elemIsInParent(event.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE) ) { // Work around a difference in the focus behaviour between Firefox, Chrome, and Safari. - // When I click the button on an already-opened notable trait popover, Safari + // When I click the button on an already-opened tooltip popover, Safari // hides the popover and then immediately shows it again, while everyone else hides it // and it stays hidden. // // To work around this, make sure the click finishes being dispatched before - // hiding the popover. Since `hideNotable()` is idempotent, this makes Safari behave + // hiding the popover. Since `hideTooltip()` is idempotent, this makes Safari behave // consistently with the other two. - setTimeout(() => hideNotable(false), 0); + setTimeout(() => hideTooltip(false), 0); } } - function hideNotable(focus) { - if (window.CURRENT_NOTABLE_ELEMENT) { - if (window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.NOTABLE_FORCE_VISIBLE) { + function hideTooltip(focus) { + if (window.CURRENT_TOOLTIP_ELEMENT) { + if (window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE) { if (focus) { - window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.focus(); + window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.focus(); } - window.CURRENT_NOTABLE_ELEMENT.NOTABLE_BASE.NOTABLE_FORCE_VISIBLE = false; + window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE = false; } const body = document.getElementsByTagName("body")[0]; - body.removeChild(window.CURRENT_NOTABLE_ELEMENT); - window.CURRENT_NOTABLE_ELEMENT = null; + body.removeChild(window.CURRENT_TOOLTIP_ELEMENT); + window.CURRENT_TOOLTIP_ELEMENT = null; } } - onEachLazy(document.getElementsByClassName("notable-traits"), e => { + onEachLazy(document.getElementsByClassName("tooltip"), e => { e.onclick = function() { - this.NOTABLE_FORCE_VISIBLE = this.NOTABLE_FORCE_VISIBLE ? false : true; - if (window.CURRENT_NOTABLE_ELEMENT && !this.NOTABLE_FORCE_VISIBLE) { - hideNotable(true); + this.TOOLTIP_FORCE_VISIBLE = this.TOOLTIP_FORCE_VISIBLE ? false : true; + if (window.CURRENT_TOOLTIP_ELEMENT && !this.TOOLTIP_FORCE_VISIBLE) { + hideTooltip(true); } else { - showNotable(this); - window.CURRENT_NOTABLE_ELEMENT.setAttribute("tabindex", "0"); - window.CURRENT_NOTABLE_ELEMENT.focus(); - window.CURRENT_NOTABLE_ELEMENT.onblur = notableBlurHandler; + showTooltip(this); + window.CURRENT_TOOLTIP_ELEMENT.setAttribute("tabindex", "0"); + window.CURRENT_TOOLTIP_ELEMENT.focus(); + window.CURRENT_TOOLTIP_ELEMENT.onblur = tooltipBlurHandler; } return false; }; @@ -933,16 +936,16 @@ function loadCss(cssUrl) { if (ev.pointerType !== "mouse") { return; } - showNotable(this); + showTooltip(this); }; e.onpointerleave = function(ev) { // If this is a synthetic touch event, ignore it. A click event will be along shortly. if (ev.pointerType !== "mouse") { return; } - if (!this.NOTABLE_FORCE_VISIBLE && - !elemIsInParent(ev.relatedTarget, window.CURRENT_NOTABLE_ELEMENT)) { - hideNotable(true); + if (!this.TOOLTIP_FORCE_VISIBLE && + !elemIsInParent(ev.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT)) { + hideTooltip(true); } }; }); @@ -1044,14 +1047,14 @@ function loadCss(cssUrl) { } /** - * Hide popover menus, notable trait tooltips, and the sidebar (if applicable). + * Hide popover menus, clickable tooltips, and the sidebar (if applicable). * - * Pass "true" to reset focus for notable traits. + * Pass "true" to reset focus for tooltip popovers. */ window.hideAllModals = function(switchFocus) { hideSidebar(); window.hidePopoverMenus(); - hideNotable(switchFocus); + hideTooltip(switchFocus); }; /** @@ -1142,7 +1145,11 @@ function loadCss(cssUrl) { (function() { let reset_button_timeout = null; - window.copy_path = but => { + const but = document.getElementById("copy-path"); + if (!but) { + return; + } + but.onclick = () => { const parent = but.parentElement; const path = []; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 88592fa0c..b98bced41 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -112,7 +112,6 @@ function levenshtein(s1, s2) { } function initSearch(rawSearchIndex) { - const MAX_LEV_DISTANCE = 3; const MAX_RESULTS = 200; const NO_TYPE_FILTER = -1; /** @@ -143,13 +142,11 @@ function initSearch(rawSearchIndex) { } function itemTypeFromName(typename) { - for (let i = 0, len = itemTypes.length; i < len; ++i) { - if (itemTypes[i] === typename) { - return i; - } + const index = itemTypes.findIndex(i => i === typename); + if (index < 0) { + throw ["Unknown type filter ", typename]; } - - throw new Error("Unknown type filter `" + typename + "`"); + return index; } /** @@ -167,21 +164,21 @@ function initSearch(rawSearchIndex) { */ function getStringElem(query, parserState, isInGenerics) { if (isInGenerics) { - throw new Error("`\"` cannot be used in generics"); + throw ["Unexpected ", "\"", " in generics"]; } else if (query.literalSearch) { - throw new Error("Cannot have more than one literal search element"); + throw ["Cannot have more than one literal search element"]; } else if (parserState.totalElems - parserState.genericsElems > 0) { - throw new Error("Cannot use literal search when there is more than one element"); + throw ["Cannot use literal search when there is more than one element"]; } parserState.pos += 1; const start = parserState.pos; const end = getIdentEndPosition(parserState); if (parserState.pos >= parserState.length) { - throw new Error("Unclosed `\"`"); + throw ["Unclosed ", "\""]; } else if (parserState.userQuery[end] !== "\"") { - throw new Error(`Unexpected \`${parserState.userQuery[end]}\` in a string element`); + throw ["Unexpected ", parserState.userQuery[end], " in a string element"]; } else if (start === end) { - throw new Error("Cannot have empty string element"); + throw ["Cannot have empty string element"]; } // To skip the quote at the end. parserState.pos += 1; @@ -260,7 +257,7 @@ function initSearch(rawSearchIndex) { return; } if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) { - throw new Error("You cannot have more than one element if you use quotes"); + throw ["You cannot have more than one element if you use quotes"]; } const pathSegments = name.split("::"); if (pathSegments.length > 1) { @@ -269,17 +266,17 @@ function initSearch(rawSearchIndex) { if (pathSegment.length === 0) { if (i === 0) { - throw new Error("Paths cannot start with `::`"); + throw ["Paths cannot start with ", "::"]; } else if (i + 1 === len) { - throw new Error("Paths cannot end with `::`"); + throw ["Paths cannot end with ", "::"]; } - throw new Error("Unexpected `::::`"); + throw ["Unexpected ", "::::"]; } } } // In case we only have something like `

`, there is no name. if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) { - throw new Error("Found generics without a path"); + throw ["Found generics without a path"]; } parserState.totalElems += 1; if (isInGenerics) { @@ -303,22 +300,23 @@ function initSearch(rawSearchIndex) { * @return {integer} */ function getIdentEndPosition(parserState) { + const start = parserState.pos; let end = parserState.pos; - let foundExclamation = false; + let foundExclamation = -1; while (parserState.pos < parserState.length) { const c = parserState.userQuery[parserState.pos]; if (!isIdentCharacter(c)) { if (c === "!") { - if (foundExclamation) { - throw new Error("Cannot have more than one `!` in an ident"); + if (foundExclamation !== -1) { + throw ["Cannot have more than one ", "!", " in an ident"]; } else if (parserState.pos + 1 < parserState.length && isIdentCharacter(parserState.userQuery[parserState.pos + 1]) ) { - throw new Error("`!` can only be at the end of an ident"); + throw ["Unexpected ", "!", ": it can only be at the end of an ident"]; } - foundExclamation = true; + foundExclamation = parserState.pos; } else if (isErrorCharacter(c)) { - throw new Error(`Unexpected \`${c}\``); + throw ["Unexpected ", c]; } else if ( isStopCharacter(c) || isSpecialStartCharacter(c) || @@ -329,16 +327,40 @@ function initSearch(rawSearchIndex) { if (!isPathStart(parserState)) { break; } + if (foundExclamation !== -1) { + if (start <= (end - 2)) { + throw ["Cannot have associated items in macros"]; + } else { + // if start == end - 1, we got the never type + // while the never type has no associated macros, we still + // can parse a path like that + foundExclamation = -1; + } + } // Skip current ":". parserState.pos += 1; - foundExclamation = false; } else { - throw new Error(`Unexpected \`${c}\``); + throw ["Unexpected ", c]; } } parserState.pos += 1; end = parserState.pos; } + // if start == end - 1, we got the never type + if (foundExclamation !== -1 && start <= (end - 2)) { + if (parserState.typeFilter === null) { + parserState.typeFilter = "macro"; + } else if (parserState.typeFilter !== "macro") { + throw [ + "Invalid search type: macro ", + "!", + " and ", + parserState.typeFilter, + " both specified", + ]; + } + end = foundExclamation; + } return end; } @@ -365,9 +387,9 @@ function initSearch(rawSearchIndex) { parserState.userQuery[parserState.pos] === "<" ) { if (isInGenerics) { - throw new Error("Unexpected `<` after `<`"); + throw ["Unexpected ", "<", " after ", "<"]; } else if (start >= end) { - throw new Error("Found generics without a path"); + throw ["Found generics without a path"]; } parserState.pos += 1; getItemsBefore(query, parserState, generics, ">"); @@ -411,24 +433,51 @@ function initSearch(rawSearchIndex) { foundStopChar = true; continue; } else if (c === ":" && isPathStart(parserState)) { - throw new Error("Unexpected `::`: paths cannot start with `::`"); + throw ["Unexpected ", "::", ": paths cannot start with ", "::"]; } else if (c === ":" || isEndCharacter(c)) { let extra = ""; if (endChar === ">") { - extra = "`<`"; + extra = "<"; } else if (endChar === "") { - extra = "`->`"; + extra = "->"; + } else { + extra = endChar; } - throw new Error("Unexpected `" + c + "` after " + extra); + throw ["Unexpected ", c, " after ", extra]; } if (!foundStopChar) { if (endChar !== "") { - throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + ", ", + " ", // whitespace + " or ", + endChar, + ", found ", + c, + ]; } - throw new Error(`Expected \`,\` or \` \`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + " or ", + " ", // whitespace + ", found ", + c, + ]; } const posBefore = parserState.pos; getNextElem(query, parserState, elems, endChar === ">"); + if (endChar !== "") { + if (parserState.pos >= parserState.length) { + throw ["Unclosed ", "<"]; + } + const c2 = parserState.userQuery[parserState.pos]; + if (!isSeparatorCharacter(c2) && c2 !== endChar) { + throw ["Expected ", endChar, ", found ", c2]; + } + } // This case can be encountered if `getNextElem` encountered a "stop character" right // from the start. For example if you have `,,` or `<>`. In this case, we simply move up // the current position to continue the parsing. @@ -437,7 +486,10 @@ function initSearch(rawSearchIndex) { } foundStopChar = false; } - // We are either at the end of the string or on the `endChar`` character, let's move forward + if (parserState.pos >= parserState.length && endChar !== "") { + throw ["Unclosed ", "<"]; + } + // We are either at the end of the string or on the `endChar` character, let's move forward // in any case. parserState.pos += 1; } @@ -453,7 +505,7 @@ function initSearch(rawSearchIndex) { for (let pos = 0; pos < parserState.pos; ++pos) { if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) { - throw new Error(`Unexpected \`${query[pos]}\` in type filter`); + throw ["Unexpected ", query[pos], " in type filter"]; } } } @@ -466,11 +518,10 @@ function initSearch(rawSearchIndex) { * @param {ParserState} parserState */ function parseInput(query, parserState) { - let c, before; let foundStopChar = true; while (parserState.pos < parserState.length) { - c = parserState.userQuery[parserState.pos]; + const c = parserState.userQuery[parserState.pos]; if (isStopCharacter(c)) { foundStopChar = true; if (isSeparatorCharacter(c)) { @@ -480,19 +531,19 @@ function initSearch(rawSearchIndex) { if (isReturnArrow(parserState)) { break; } - throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`); + throw ["Unexpected ", c, " (did you mean ", "->", "?)"]; } - throw new Error(`Unexpected \`${c}\``); + throw ["Unexpected ", c]; } else if (c === ":" && !isPathStart(parserState)) { if (parserState.typeFilter !== null) { - throw new Error("Unexpected `:`"); + throw ["Unexpected ", ":"]; } if (query.elems.length === 0) { - throw new Error("Expected type filter before `:`"); + throw ["Expected type filter before ", ":"]; } else if (query.elems.length !== 1 || parserState.totalElems !== 1) { - throw new Error("Unexpected `:`"); + throw ["Unexpected ", ":"]; } else if (query.literalSearch) { - throw new Error("You cannot use quotes on type filter"); + throw ["You cannot use quotes on type filter"]; } checkExtraTypeFilterCharacters(parserState); // The type filter doesn't count as an element since it's a modifier. @@ -505,11 +556,31 @@ function initSearch(rawSearchIndex) { } if (!foundStopChar) { if (parserState.typeFilter !== null) { - throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``); + throw [ + "Expected ", + ",", // comma + ", ", + " ", // whitespace + " or ", + "->", // arrow + ", found ", + c, + ]; } - throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``); - } - before = query.elems.length; + throw [ + "Expected ", + ",", // comma + ", ", + " ", // whitespace + ", ", + ":", // colon + " or ", + "->", // arrow + ", found ", + c, + ]; + } + const before = query.elems.length; getNextElem(query, parserState, query.elems, false); if (query.elems.length === before) { // Nothing was added, weird... Let's increase the position to not remain stuck. @@ -518,14 +589,13 @@ function initSearch(rawSearchIndex) { foundStopChar = false; } while (parserState.pos < parserState.length) { - c = parserState.userQuery[parserState.pos]; if (isReturnArrow(parserState)) { parserState.pos += 2; // Get returned elements. getItemsBefore(query, parserState, query.returned, ""); // Nothing can come afterward! if (query.returned.length === 0) { - throw new Error("Expected at least one item after `->`"); + throw ["Expected at least one item after ", "->"]; } break; } else { @@ -594,8 +664,8 @@ function initSearch(rawSearchIndex) { * * The supported syntax by this parser is as follow: * - * ident = *(ALPHA / DIGIT / "_") [!] - * path = ident *(DOUBLE-COLON ident) + * ident = *(ALPHA / DIGIT / "_") + * path = ident *(DOUBLE-COLON ident) [!] * arg = path [generics] * arg-without-generic = path * type-sep = COMMA/WS *(COMMA/WS) @@ -679,7 +749,7 @@ function initSearch(rawSearchIndex) { } } catch (err) { query = newParsedQuery(userQuery); - query.error = err.message; + query.error = err; query.typeFilter = -1; return query; } @@ -897,13 +967,13 @@ function initSearch(rawSearchIndex) { * @param {QueryElement} elem - The element from the parsed query. * @param {integer} defaultLev - This is the value to return in case there are no generics. * - * @return {integer} - Returns the best match (if any) or `MAX_LEV_DISTANCE + 1`. + * @return {integer} - Returns the best match (if any) or `maxLevDistance + 1`. */ - function checkGenerics(row, elem, defaultLev) { + function checkGenerics(row, elem, defaultLev, maxLevDistance) { if (row.generics.length === 0) { - return elem.generics.length === 0 ? defaultLev : MAX_LEV_DISTANCE + 1; + return elem.generics.length === 0 ? defaultLev : maxLevDistance + 1; } else if (row.generics.length > 0 && row.generics[0].name === null) { - return checkGenerics(row.generics[0], elem, defaultLev); + return checkGenerics(row.generics[0], elem, defaultLev, maxLevDistance); } // The names match, but we need to be sure that all generics kinda // match as well. @@ -914,8 +984,8 @@ function initSearch(rawSearchIndex) { elem_name = entry.name; if (elem_name === "") { // Pure generic, needs to check into it. - if (checkGenerics(entry, elem, MAX_LEV_DISTANCE + 1) !== 0) { - return MAX_LEV_DISTANCE + 1; + if (checkGenerics(entry, elem, maxLevDistance + 1, maxLevDistance) !== 0) { + return maxLevDistance + 1; } continue; } @@ -942,7 +1012,7 @@ function initSearch(rawSearchIndex) { } } if (match === null) { - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } elems[match] -= 1; if (elems[match] === 0) { @@ -951,7 +1021,7 @@ function initSearch(rawSearchIndex) { } return 0; } - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } /** @@ -963,10 +1033,10 @@ function initSearch(rawSearchIndex) { * * @return {integer} - Returns a Levenshtein distance to the best match. */ - function checkIfInGenerics(row, elem) { - let lev = MAX_LEV_DISTANCE + 1; + function checkIfInGenerics(row, elem, maxLevDistance) { + let lev = maxLevDistance + 1; for (const entry of row.generics) { - lev = Math.min(checkType(entry, elem, true), lev); + lev = Math.min(checkType(entry, elem, true, maxLevDistance), lev); if (lev === 0) { break; } @@ -983,15 +1053,15 @@ function initSearch(rawSearchIndex) { * @param {boolean} literalSearch * * @return {integer} - Returns a Levenshtein distance to the best match. If there is - * no match, returns `MAX_LEV_DISTANCE + 1`. + * no match, returns `maxLevDistance + 1`. */ - function checkType(row, elem, literalSearch) { + function checkType(row, elem, literalSearch, maxLevDistance) { if (row.name === null) { // This is a pure "generic" search, no need to run other checks. if (row.generics.length > 0) { - return checkIfInGenerics(row, elem); + return checkIfInGenerics(row, elem, maxLevDistance); } - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } let lev = levenshtein(row.name, elem.name); @@ -1005,9 +1075,9 @@ function initSearch(rawSearchIndex) { return 0; } } - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } else if (elem.generics.length > 0) { - return checkGenerics(row, elem, MAX_LEV_DISTANCE + 1); + return checkGenerics(row, elem, maxLevDistance + 1, maxLevDistance); } return 0; } else if (row.generics.length > 0) { @@ -1017,22 +1087,20 @@ function initSearch(rawSearchIndex) { } // The name didn't match so we now check if the type we're looking for is inside // the generics! - lev = checkIfInGenerics(row, elem); - // Now whatever happens, the returned distance is "less good" so we should mark - // it as such, and so we add 0.5 to the distance to make it "less good". - return lev + 0.5; - } else if (lev > MAX_LEV_DISTANCE) { + lev = Math.min(lev, checkIfInGenerics(row, elem, maxLevDistance)); + return lev; + } else if (lev > maxLevDistance) { // So our item's name doesn't match at all and has generics. // // Maybe it's present in a sub generic? For example "f>>()", if we're // looking for "B", we'll need to go down. - return checkIfInGenerics(row, elem); + return checkIfInGenerics(row, elem, maxLevDistance); } else { // At this point, the name kinda match and we have generics to check, so // let's go! - const tmp_lev = checkGenerics(row, elem, lev); - if (tmp_lev > MAX_LEV_DISTANCE) { - return MAX_LEV_DISTANCE + 1; + const tmp_lev = checkGenerics(row, elem, lev, maxLevDistance); + if (tmp_lev > maxLevDistance) { + return maxLevDistance + 1; } // We compute the median value of both checks and return it. return (tmp_lev + lev) / 2; @@ -1040,7 +1108,7 @@ function initSearch(rawSearchIndex) { } else if (elem.generics.length > 0) { // In this case, we were expecting generics but there isn't so we simply reject this // one. - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } // No generics on our query or on the target type so we can return without doing // anything else. @@ -1055,23 +1123,26 @@ function initSearch(rawSearchIndex) { * @param {integer} typeFilter * * @return {integer} - Returns a Levenshtein distance to the best match. If there is no - * match, returns `MAX_LEV_DISTANCE + 1`. + * match, returns `maxLevDistance + 1`. */ - function findArg(row, elem, typeFilter) { - let lev = MAX_LEV_DISTANCE + 1; + function findArg(row, elem, typeFilter, maxLevDistance) { + let lev = maxLevDistance + 1; if (row && row.type && row.type.inputs && row.type.inputs.length > 0) { for (const input of row.type.inputs) { if (!typePassesFilter(typeFilter, input.ty)) { continue; } - lev = Math.min(lev, checkType(input, elem, parsedQuery.literalSearch)); + lev = Math.min( + lev, + checkType(input, elem, parsedQuery.literalSearch, maxLevDistance) + ); if (lev === 0) { return 0; } } } - return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev; + return parsedQuery.literalSearch ? maxLevDistance + 1 : lev; } /** @@ -1082,10 +1153,10 @@ function initSearch(rawSearchIndex) { * @param {integer} typeFilter * * @return {integer} - Returns a Levenshtein distance to the best match. If there is no - * match, returns `MAX_LEV_DISTANCE + 1`. + * match, returns `maxLevDistance + 1`. */ - function checkReturned(row, elem, typeFilter) { - let lev = MAX_LEV_DISTANCE + 1; + function checkReturned(row, elem, typeFilter, maxLevDistance) { + let lev = maxLevDistance + 1; if (row && row.type && row.type.output.length > 0) { const ret = row.type.output; @@ -1093,20 +1164,23 @@ function initSearch(rawSearchIndex) { if (!typePassesFilter(typeFilter, ret_ty.ty)) { continue; } - lev = Math.min(lev, checkType(ret_ty, elem, parsedQuery.literalSearch)); + lev = Math.min( + lev, + checkType(ret_ty, elem, parsedQuery.literalSearch, maxLevDistance) + ); if (lev === 0) { return 0; } } } - return parsedQuery.literalSearch ? MAX_LEV_DISTANCE + 1 : lev; + return parsedQuery.literalSearch ? maxLevDistance + 1 : lev; } - function checkPath(contains, ty) { + function checkPath(contains, ty, maxLevDistance) { if (contains.length === 0) { return 0; } - let ret_lev = MAX_LEV_DISTANCE + 1; + let ret_lev = maxLevDistance + 1; const path = ty.path.split("::"); if (ty.parent && ty.parent.name) { @@ -1116,7 +1190,7 @@ function initSearch(rawSearchIndex) { const length = path.length; const clength = contains.length; if (clength > length) { - return MAX_LEV_DISTANCE + 1; + return maxLevDistance + 1; } for (let i = 0; i < length; ++i) { if (i + clength > length) { @@ -1126,7 +1200,7 @@ function initSearch(rawSearchIndex) { let aborted = false; for (let x = 0; x < clength; ++x) { const lev = levenshtein(path[i + x], contains[x]); - if (lev > MAX_LEV_DISTANCE) { + if (lev > maxLevDistance) { aborted = true; break; } @@ -1231,7 +1305,7 @@ function initSearch(rawSearchIndex) { * following condition: * * * If it is a "literal search" (`parsedQuery.literalSearch`), then `lev` must be 0. - * * If it is not a "literal search", `lev` must be <= `MAX_LEV_DISTANCE`. + * * If it is not a "literal search", `lev` must be <= `maxLevDistance`. * * The `results` map contains information which will be used to sort the search results: * @@ -1249,8 +1323,8 @@ function initSearch(rawSearchIndex) { * @param {integer} lev * @param {integer} path_lev */ - function addIntoResults(results, fullId, id, index, lev, path_lev) { - const inBounds = lev <= MAX_LEV_DISTANCE || index !== -1; + function addIntoResults(results, fullId, id, index, lev, path_lev, maxLevDistance) { + const inBounds = lev <= maxLevDistance || index !== -1; if (lev === 0 || (!parsedQuery.literalSearch && inBounds)) { if (results[fullId] !== undefined) { const result = results[fullId]; @@ -1289,7 +1363,8 @@ function initSearch(rawSearchIndex) { elem, results_others, results_in_args, - results_returned + results_returned, + maxLevDistance ) { if (!row || (filterCrates !== null && row.crate !== filterCrates)) { return; @@ -1298,13 +1373,13 @@ function initSearch(rawSearchIndex) { const fullId = row.id; const searchWord = searchWords[pos]; - const in_args = findArg(row, elem, parsedQuery.typeFilter); - const returned = checkReturned(row, elem, parsedQuery.typeFilter); + const in_args = findArg(row, elem, parsedQuery.typeFilter, maxLevDistance); + const returned = checkReturned(row, elem, parsedQuery.typeFilter, maxLevDistance); // path_lev is 0 because no parent path information is currently stored // in the search index - addIntoResults(results_in_args, fullId, pos, -1, in_args, 0); - addIntoResults(results_returned, fullId, pos, -1, returned, 0); + addIntoResults(results_in_args, fullId, pos, -1, in_args, 0, maxLevDistance); + addIntoResults(results_returned, fullId, pos, -1, returned, 0, maxLevDistance); if (!typePassesFilter(parsedQuery.typeFilter, row.ty)) { return; @@ -1328,16 +1403,16 @@ function initSearch(rawSearchIndex) { // No need to check anything else if it's a "pure" generics search. if (elem.name.length === 0) { if (row.type !== null) { - lev = checkGenerics(row.type, elem, MAX_LEV_DISTANCE + 1); + lev = checkGenerics(row.type, elem, maxLevDistance + 1, maxLevDistance); // path_lev is 0 because we know it's empty - addIntoResults(results_others, fullId, pos, index, lev, 0); + addIntoResults(results_others, fullId, pos, index, lev, 0, maxLevDistance); } return; } if (elem.fullPath.length > 1) { - path_lev = checkPath(elem.pathWithoutLast, row); - if (path_lev > MAX_LEV_DISTANCE) { + path_lev = checkPath(elem.pathWithoutLast, row, maxLevDistance); + if (path_lev > maxLevDistance) { return; } } @@ -1351,11 +1426,11 @@ function initSearch(rawSearchIndex) { lev = levenshtein(searchWord, elem.pathLast); - if (index === -1 && lev + path_lev > MAX_LEV_DISTANCE) { + if (index === -1 && lev + path_lev > maxLevDistance) { return; } - addIntoResults(results_others, fullId, pos, index, lev, path_lev); + addIntoResults(results_others, fullId, pos, index, lev, path_lev, maxLevDistance); } /** @@ -1367,7 +1442,7 @@ function initSearch(rawSearchIndex) { * @param {integer} pos - Position in the `searchIndex`. * @param {Object} results */ - function handleArgs(row, pos, results) { + function handleArgs(row, pos, results, maxLevDistance) { if (!row || (filterCrates !== null && row.crate !== filterCrates)) { return; } @@ -1379,7 +1454,7 @@ function initSearch(rawSearchIndex) { function checkArgs(elems, callback) { for (const elem of elems) { // There is more than one parameter to the query so all checks should be "exact" - const lev = callback(row, elem, NO_TYPE_FILTER); + const lev = callback(row, elem, NO_TYPE_FILTER, maxLevDistance); if (lev <= 1) { nbLev += 1; totalLev += lev; @@ -1400,12 +1475,21 @@ function initSearch(rawSearchIndex) { return; } const lev = Math.round(totalLev / nbLev); - addIntoResults(results, row.id, pos, 0, lev, 0); + addIntoResults(results, row.id, pos, 0, lev, 0, maxLevDistance); } function innerRunQuery() { let elem, i, nSearchWords, in_returned, row; + let queryLen = 0; + for (const elem of parsedQuery.elems) { + queryLen += elem.name.length; + } + for (const elem of parsedQuery.returned) { + queryLen += elem.name.length; + } + const maxLevDistance = Math.floor(queryLen / 3); + if (parsedQuery.foundElems === 1) { if (parsedQuery.elems.length === 1) { elem = parsedQuery.elems[0]; @@ -1418,7 +1502,8 @@ function initSearch(rawSearchIndex) { elem, results_others, results_in_args, - results_returned + results_returned, + maxLevDistance ); } } else if (parsedQuery.returned.length === 1) { @@ -1426,13 +1511,18 @@ function initSearch(rawSearchIndex) { elem = parsedQuery.returned[0]; for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) { row = searchIndex[i]; - in_returned = checkReturned(row, elem, parsedQuery.typeFilter); - addIntoResults(results_others, row.id, i, -1, in_returned); + in_returned = checkReturned( + row, + elem, + parsedQuery.typeFilter, + maxLevDistance + ); + addIntoResults(results_others, row.id, i, -1, in_returned, maxLevDistance); } } } else if (parsedQuery.foundElems > 0) { for (i = 0, nSearchWords = searchWords.length; i < nSearchWords; ++i) { - handleArgs(searchIndex[i], i, results_others); + handleArgs(searchIndex[i], i, results_others, maxLevDistance); } } } @@ -1470,7 +1560,7 @@ function initSearch(rawSearchIndex) { * * @return {boolean} - Whether the result is valid or not */ - function validateResult(name, path, keys, parent) { + function validateResult(name, path, keys, parent, maxLevDistance) { if (!keys || !keys.length) { return true; } @@ -1485,7 +1575,7 @@ function initSearch(rawSearchIndex) { (parent !== undefined && parent.name !== undefined && parent.name.toLowerCase().indexOf(key) > -1) || // lastly check to see if the name was a levenshtein match - levenshtein(name, key) <= MAX_LEV_DISTANCE)) { + levenshtein(name, key) <= maxLevDistance)) { return false; } } @@ -1725,7 +1815,16 @@ function initSearch(rawSearchIndex) { let output = `

Results${crates}

`; if (results.query.error !== null) { - output += `

Query parser error: "${results.query.error}".

`; + const error = results.query.error; + error.forEach((value, index) => { + value = value.split("<").join("<").split(">").join(">"); + if (index % 2 !== 0) { + error[index] = `${value}`; + } else { + error[index] = value; + } + }); + output += `

Query parser error: "${error.join("")}".

`; output += "
" + makeTabHeader(0, "In Names", ret_others[1]) + "
"; @@ -1922,7 +2021,7 @@ function initSearch(rawSearchIndex) { * @type {Array} */ const searchWords = []; - let i, word; + const charA = "A".charCodeAt(0); let currentIndex = 0; let id = 0; @@ -1936,7 +2035,7 @@ function initSearch(rawSearchIndex) { /** * The raw search data for a given crate. `n`, `t`, `d`, and `q`, `i`, and `f` * are arrays with the same length. n[i] contains the name of an item. - * t[i] contains the type of that item (as a small integer that represents an + * 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[i] contains the full path of the item, or an empty string indicating @@ -1963,7 +2062,7 @@ function initSearch(rawSearchIndex) { * doc: string, * a: Object, * n: Array, - * t: Array, + * t: String, * d: Array, * q: Array, * i: Array, @@ -1992,7 +2091,7 @@ function initSearch(rawSearchIndex) { searchIndex.push(crateRow); currentIndex += 1; - // an array of (Number) item types + // a String of one character item type codes const itemTypes = crateCorpus.t; // an array of (String) item names const itemNames = crateCorpus.n; @@ -2017,7 +2116,7 @@ function initSearch(rawSearchIndex) { // convert `rawPaths` entries into object form // generate normalizedPaths for function search mode let len = paths.length; - for (i = 0; i < len; ++i) { + for (let i = 0; i < len; ++i) { lowercasePaths.push({ty: paths[i][0], name: paths[i][1].toLowerCase()}); paths[i] = {ty: paths[i][0], name: paths[i][1]}; } @@ -2031,19 +2130,17 @@ function initSearch(rawSearchIndex) { // faster analysis operations len = itemTypes.length; let lastPath = ""; - for (i = 0; i < len; ++i) { + for (let i = 0; i < len; ++i) { + let word = ""; // This object should have exactly the same set of fields as the "crateRow" // object defined above. if (typeof itemNames[i] === "string") { word = itemNames[i].toLowerCase(); - searchWords.push(word); - } else { - word = ""; - searchWords.push(""); } + searchWords.push(word); const row = { crate: crate, - ty: itemTypes[i], + ty: itemTypes.charCodeAt(i) - charA, name: itemNames[i], path: itemPaths[i] ? itemPaths[i] : lastPath, desc: itemDescs[i], diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 84df1b7d3..1cd552e7f 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -1,5 +1,5 @@ // Local js definitions: -/* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */ +/* global getSettingValue, getVirtualKey, updateLocalStorage, updateTheme */ /* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */ /* global MAIN_ID, getVar, getSettingsButton */ @@ -19,7 +19,7 @@ case "theme": case "preferred-dark-theme": case "preferred-light-theme": - updateSystemTheme(); + updateTheme(); updateLightAndDark(); break; case "line-numbers": @@ -48,13 +48,13 @@ } function showLightAndDark() { - removeClass(document.getElementById("preferred-light-theme").parentElement, "hidden"); - removeClass(document.getElementById("preferred-dark-theme").parentElement, "hidden"); + removeClass(document.getElementById("preferred-light-theme"), "hidden"); + removeClass(document.getElementById("preferred-dark-theme"), "hidden"); } function hideLightAndDark() { - addClass(document.getElementById("preferred-light-theme").parentElement, "hidden"); - addClass(document.getElementById("preferred-dark-theme").parentElement, "hidden"); + addClass(document.getElementById("preferred-light-theme"), "hidden"); + addClass(document.getElementById("preferred-dark-theme"), "hidden"); } function updateLightAndDark() { @@ -80,17 +80,6 @@ toggle.onkeyup = handleKey; toggle.onkeyrelease = handleKey; }); - onEachLazy(settingsElement.getElementsByClassName("select-wrapper"), elem => { - const select = elem.getElementsByTagName("select")[0]; - const settingId = select.id; - const settingValue = getSettingValue(settingId); - if (settingValue !== null) { - select.value = settingValue; - } - select.onchange = function() { - changeSetting(this.id, this.value); - }; - }); onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"), elem => { const settingId = elem.name; let settingValue = getSettingValue(settingId); @@ -127,38 +116,40 @@ let output = ""; for (const setting of settings) { - output += "
"; const js_data_name = setting["js_name"]; const setting_name = setting["name"]; if (setting["options"] !== undefined) { // This is a select setting. output += `\ -
-
${setting_name}
-
`; +
+
${setting_name}
+
`; onEach(setting["options"], option => { const checked = option === setting["default"] ? " checked" : ""; const full = `${js_data_name}-${option.replace(/ /g,"-")}`; output += `\ -`; + `; }); - output += "
"; + output += `\ +
+
`; } else { // This is a checkbox toggle. const checked = setting["default"] === true ? " checked" : ""; output += `\ -`; +
\ + \ +
`; } - output += "
"; } return output; } diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index 0e1c864e6..6c0f03b5b 100644 --- a/src/librustdoc/html/static/js/source-script.js +++ b/src/librustdoc/html/static/js/source-script.js @@ -117,8 +117,7 @@ function createSourceSidebar() { sidebar.appendChild(title); Object.keys(sourcesIndex).forEach(key => { sourcesIndex[key][NAME_OFFSET] = key; - hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "", - hasFoundFile); + hasFoundFile = createDirEntry(sourcesIndex[key], sidebar, "", hasFoundFile); }); container.appendChild(sidebar); diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index db2db83ca..c72ac254f 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -51,7 +51,6 @@ function hasClass(elem, className) { return elem && elem.classList && elem.classList.contains(className); } -// eslint-disable-next-line no-unused-vars function addClass(elem, className) { if (!elem || !elem.classList) { return; @@ -153,79 +152,74 @@ function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) { } } -// This function is called from "main.js". -// eslint-disable-next-line no-unused-vars -function useSystemTheme(value) { - if (value === undefined) { - value = true; - } - - updateLocalStorage("use-system-theme", value); - - // update the toggle if we're on the settings page - const toggle = document.getElementById("use-system-theme"); - if (toggle && toggle instanceof HTMLInputElement) { - toggle.checked = value; - } -} - -const updateSystemTheme = (function() { - if (!window.matchMedia) { - // fallback to the CSS computed value - return () => { - const cssTheme = getComputedStyle(document.documentElement) - .getPropertyValue("content"); - - switchTheme( - window.currentTheme, - window.mainTheme, - JSON.parse(cssTheme) || "light", - true - ); +const updateTheme = (function() { + /** + * Update the current theme to match whatever the current combination of + * * the preference for using the system theme + * (if this is the case, the value of preferred-light-theme, if the + * system theme is light, otherwise if dark, the value of + * preferred-dark-theme.) + * * the preferred theme + * … dictates that it should be. + */ + function updateTheme() { + const use = (theme, saveTheme) => { + switchTheme(window.currentTheme, window.mainTheme, theme, saveTheme); }; - } - - // only listen to (prefers-color-scheme: dark) because light is the default - const mql = window.matchMedia("(prefers-color-scheme: dark)"); - function handlePreferenceChange(mql) { - const use = theme => { - switchTheme(window.currentTheme, window.mainTheme, theme, true); - }; // maybe the user has disabled the setting in the meantime! if (getSettingValue("use-system-theme") !== "false") { const lightTheme = getSettingValue("preferred-light-theme") || "light"; const darkTheme = getSettingValue("preferred-dark-theme") || "dark"; - if (mql.matches) { - use(darkTheme); + if (isDarkMode()) { + use(darkTheme, true); } else { // prefers a light theme, or has no preference - use(lightTheme); + use(lightTheme, true); } // note: we save the theme so that it doesn't suddenly change when // the user disables "use-system-theme" and reloads the page or // navigates to another page } else { - use(getSettingValue("theme")); + use(getSettingValue("theme"), false); } } - mql.addListener(handlePreferenceChange); + // This is always updated below to a function () => bool. + let isDarkMode; - return () => { - handlePreferenceChange(mql); - }; -})(); + // Determine the function for isDarkMode, and if we have + // `window.matchMedia`, set up an event listener on the preferred color + // scheme. + // + // Otherwise, fall back to the prefers-color-scheme value CSS captured in + // the "content" property. + if (window.matchMedia) { + // only listen to (prefers-color-scheme: dark) because light is the default + const mql = window.matchMedia("(prefers-color-scheme: dark)"); -function switchToSavedTheme() { - switchTheme( - window.currentTheme, - window.mainTheme, - getSettingValue("theme") || "light", - false - ); -} + isDarkMode = () => mql.matches; + + if (mql.addEventListener) { + mql.addEventListener("change", updateTheme); + } else { + // This is deprecated, see: + // https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/addListener + mql.addListener(updateTheme); + } + } else { + // fallback to the CSS computed value + const cssContent = getComputedStyle(document.documentElement) + .getPropertyValue("content"); + // (Note: the double-quotes come from that this is a CSS value, which + // might be a length, string, etc.) + const cssColorScheme = cssContent || "\"light\""; + isDarkMode = () => (cssColorScheme === "\"dark\""); + } + + return updateTheme; +})(); if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) { // update the preferred dark theme if the user is already using a dark theme @@ -235,13 +229,10 @@ if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) { && darkThemes.indexOf(localStoredTheme) >= 0) { updateLocalStorage("preferred-dark-theme", localStoredTheme); } - - // call the function to initialize the theme at least once! - updateSystemTheme(); -} else { - switchToSavedTheme(); } +updateTheme(); + if (getSettingValue("source-sidebar-show") === "true") { // At this point in page load, `document.body` is not available yet. // Set a class on the `` element instead. @@ -259,6 +250,6 @@ if (getSettingValue("source-sidebar-show") === "true") { // specifically when talking to a remote website with no caching. window.addEventListener("pageshow", ev => { if (ev.persisted) { - setTimeout(switchToSavedTheme, 0); + setTimeout(updateTheme, 0); } }); -- cgit v1.2.3