Skip to content

Commit

Permalink
Rollup merge of rust-lang#108584 - GuillaumeGomez:rustdoc-search-back…
Browse files Browse the repository at this point in the history
…ground, r=notriddle

Put backtick content from rustdoc search errors into a <code> elements

Some screenshots of the result:

![Screenshot from 2023-02-28 22-37-09](https://user-images.githubusercontent.com/3050060/221990290-fa84f1cf-5a64-4ce5-8433-ee36cedf4c00.png)
![Screenshot from 2023-02-28 22-36-59](https://user-images.githubusercontent.com/3050060/221990298-f8177eeb-894b-4fce-a6fc-06d17c8b7ca2.png)
![Screenshot from 2023-02-28 22-36-51](https://user-images.githubusercontent.com/3050060/221990301-41bffd64-d041-41f1-995a-983925b1fbb1.png)

You can test it [here](https://rustdoc.crud.net/imperio/rustdoc-search-background/foo/index.html?search=%22).

r? `@notriddle`
  • Loading branch information
compiler-errors authored Mar 2, 2023
2 parents 017069d + cfb4af8 commit 96e5b5d
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 43 deletions.
1 change: 0 additions & 1 deletion src/librustdoc/html/static/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
}
};
5 changes: 5 additions & 0 deletions src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,11 @@ a.tooltip:hover::after {
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;
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/html/static/css/themes/ayu.css
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ 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;
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/html/static/css/themes/dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
--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;
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/html/static/css/themes/light.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
--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;
Expand Down
130 changes: 91 additions & 39 deletions src/librustdoc/html/static/js/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ function initSearch(rawSearchIndex) {
function itemTypeFromName(typename) {
const index = itemTypes.findIndex(i => i === typename);
if (index < 0) {
throw new Error("Unknown type filter `" + typename + "`");
throw ["Unknown type filter ", typename];
}
return index;
}
Expand All @@ -164,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;
Expand Down Expand Up @@ -257,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) {
Expand All @@ -266,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 `<p>`, 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) {
Expand Down Expand Up @@ -308,15 +308,15 @@ function initSearch(rawSearchIndex) {
if (!isIdentCharacter(c)) {
if (c === "!") {
if (foundExclamation !== -1) {
throw new Error("Cannot have more than one `!` in an ident");
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 = parserState.pos;
} else if (isErrorCharacter(c)) {
throw new Error(`Unexpected \`${c}\``);
throw ["Unexpected ", c];
} else if (
isStopCharacter(c) ||
isSpecialStartCharacter(c) ||
Expand All @@ -329,7 +329,7 @@ function initSearch(rawSearchIndex) {
}
if (foundExclamation !== -1) {
if (start <= (end - 2)) {
throw new Error("Cannot have associated items in macros");
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
Expand All @@ -340,7 +340,7 @@ function initSearch(rawSearchIndex) {
// Skip current ":".
parserState.pos += 1;
} else {
throw new Error(`Unexpected \`${c}\``);
throw ["Unexpected ", c];
}
}
parserState.pos += 1;
Expand All @@ -351,8 +351,13 @@ function initSearch(rawSearchIndex) {
if (parserState.typeFilter === null) {
parserState.typeFilter = "macro";
} else if (parserState.typeFilter !== "macro") {
throw new Error("Invalid search type: macro `!` and " +
`\`${parserState.typeFilter}\` both specified`);
throw [
"Invalid search type: macro ",
"!",
" and ",
parserState.typeFilter,
" both specified",
];
}
end = foundExclamation;
}
Expand Down Expand Up @@ -382,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, ">");
Expand Down Expand Up @@ -428,21 +433,39 @@ 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
", ",
"&nbsp;", // whitespace
" or ",
endChar,
", found ",
c,
];
}
throw new Error(`Expected \`,\` or \` \`, found \`${c}\``);
throw [
"Expected ",
",", // comma
" or ",
"&nbsp;", // whitespace
", found ",
c,
];
}
const posBefore = parserState.pos;
getNextElem(query, parserState, elems, endChar === ">");
Expand Down Expand Up @@ -470,7 +493,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"];
}
}
}
Expand All @@ -496,19 +519,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.
Expand All @@ -521,9 +544,29 @@ function initSearch(rawSearchIndex) {
}
if (!foundStopChar) {
if (parserState.typeFilter !== null) {
throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``);
throw [
"Expected ",
",", // comma
", ",
"&nbsp;", // whitespace
" or ",
"->", // arrow
", found ",
c,
];
}
throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``);
throw [
"Expected ",
",", // comma
", ",
"&nbsp;", // whitespace
", ",
":", // colon
" or ",
"->", // arrow
", found ",
c,
];
}
const before = query.elems.length;
getNextElem(query, parserState, query.elems, false);
Expand All @@ -540,7 +583,7 @@ function initSearch(rawSearchIndex) {
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 {
Expand Down Expand Up @@ -694,7 +737,7 @@ function initSearch(rawSearchIndex) {
}
} catch (err) {
query = newParsedQuery(userQuery);
query.error = err.message;
query.error = err;
query.typeFilter = -1;
return query;
}
Expand Down Expand Up @@ -1760,7 +1803,16 @@ function initSearch(rawSearchIndex) {

let output = `<h1 class="search-results-title">Results${crates}</h1>`;
if (results.query.error !== null) {
output += `<h3>Query parser error: "${results.query.error}".</h3>`;
const error = results.query.error;
error.forEach((value, index) => {
value = value.split("<").join("&lt;").split(">").join("&gt;");
if (index % 2 !== 0) {
error[index] = `<code>${value}</code>`;
} else {
error[index] = value;
}
});
output += `<h3 class="error">Query parser error: "${error.join("")}".</h3>`;
output += "<div id=\"search-tabs\">" +
makeTabHeader(0, "In Names", ret_others[1]) +
"</div>";
Expand Down
14 changes: 13 additions & 1 deletion src/tools/rustdoc-js/tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,20 @@ function valueCheck(fullPath, expected, result, error_text, queryName) {
error_text.push('==> Unknown key "' + key + '"');
break;
}
let result_v = result[key];
if (result_v !== null && key === "error") {
result_v.forEach((value, index) => {
value = value.split("&nbsp;").join(" ");
if (index % 2 === 1) {
result_v[index] = "`" + value + "`";
} else {
result_v[index] = value;
}
});
result_v = result_v.join("");
}
const obj_path = fullPath + (fullPath.length > 0 ? '.' : '') + key;
valueCheck(obj_path, expected[key], result[key], error_text, queryName);
valueCheck(obj_path, expected[key], result_v, error_text, queryName);
}
} else {
expectedValue = JSON.stringify(expected);
Expand Down
39 changes: 39 additions & 0 deletions tests/rustdoc-gui/search-error.goml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Checks that the crate search filtering is handled correctly and changes the results.
goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds"
show-text: true

define-function: (
"check-colors",
(theme, error_background),
block {
// Setting the theme.
local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
// We reload the page so the local storage settings are being used.
reload:

wait-for: "#search .error code"
assert-css: ("#search .error code", {"background-color": |error_background|})
}
)

call-function: (
"check-colors",
{
"theme": "ayu",
"error_background": "rgb(79, 76, 76)",
},
)
call-function: (
"check-colors",
{
"theme": "dark",
"error_background": "rgb(72, 72, 72)",
},
)
call-function: (
"check-colors",
{
"theme": "light",
"error_background": "rgb(208, 204, 204)",
},
)
Loading

0 comments on commit 96e5b5d

Please sign in to comment.