Skip to content

Commit 96e5b5d

Browse files
Rollup merge of rust-lang#108584 - GuillaumeGomez:rustdoc-search-background, 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`
2 parents 017069d + cfb4af8 commit 96e5b5d

File tree

9 files changed

+153
-43
lines changed

9 files changed

+153
-43
lines changed

src/librustdoc/html/static/.eslintrc.js

-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ module.exports = {
9090
"no-return-assign": "error",
9191
"no-script-url": "error",
9292
"no-sequences": "error",
93-
"no-throw-literal": "error",
9493
"no-div-regex": "error",
9594
}
9695
};

src/librustdoc/html/static/css/rustdoc.css

+5
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,11 @@ a.tooltip:hover::after {
12601260
color: var(--search-tab-title-count-color);
12611261
}
12621262

1263+
#search .error code {
1264+
border-radius: 3px;
1265+
background-color: var(--search-error-code-background-color);
1266+
}
1267+
12631268
#src-sidebar-toggle {
12641269
position: sticky;
12651270
top: 0;

src/librustdoc/html/static/css/themes/ayu.css

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
4343
--search-result-link-focus-background-color: #3c3c3c;
4444
--search-result-border-color: #aaa3;
4545
--search-color: #fff;
46+
--search-error-code-background-color: #4f4c4c;
4647
--search-results-alias-color: #c5c5c5;
4748
--search-results-grey-color: #999;
4849
--search-tab-title-count-color: #888;

src/librustdoc/html/static/css/themes/dark.css

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
--search-result-link-focus-background-color: #616161;
3939
--search-result-border-color: #aaa3;
4040
--search-color: #111;
41+
--search-error-code-background-color: #484848;
4142
--search-results-alias-color: #fff;
4243
--search-results-grey-color: #ccc;
4344
--search-tab-title-count-color: #888;

src/librustdoc/html/static/css/themes/light.css

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
--search-result-link-focus-background-color: #ccc;
3939
--search-result-border-color: #aaa3;
4040
--search-color: #000;
41+
--search-error-code-background-color: #d0cccc;
4142
--search-results-alias-color: #000;
4243
--search-results-grey-color: #999;
4344
--search-tab-title-count-color: #888;

src/librustdoc/html/static/js/search.js

+91-39
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ function initSearch(rawSearchIndex) {
144144
function itemTypeFromName(typename) {
145145
const index = itemTypes.findIndex(i => i === typename);
146146
if (index < 0) {
147-
throw new Error("Unknown type filter `" + typename + "`");
147+
throw ["Unknown type filter ", typename];
148148
}
149149
return index;
150150
}
@@ -164,21 +164,21 @@ function initSearch(rawSearchIndex) {
164164
*/
165165
function getStringElem(query, parserState, isInGenerics) {
166166
if (isInGenerics) {
167-
throw new Error("`\"` cannot be used in generics");
167+
throw ["Unexpected ", "\"", " in generics"];
168168
} else if (query.literalSearch) {
169-
throw new Error("Cannot have more than one literal search element");
169+
throw ["Cannot have more than one literal search element"];
170170
} else if (parserState.totalElems - parserState.genericsElems > 0) {
171-
throw new Error("Cannot use literal search when there is more than one element");
171+
throw ["Cannot use literal search when there is more than one element"];
172172
}
173173
parserState.pos += 1;
174174
const start = parserState.pos;
175175
const end = getIdentEndPosition(parserState);
176176
if (parserState.pos >= parserState.length) {
177-
throw new Error("Unclosed `\"`");
177+
throw ["Unclosed ", "\""];
178178
} else if (parserState.userQuery[end] !== "\"") {
179-
throw new Error(`Unexpected \`${parserState.userQuery[end]}\` in a string element`);
179+
throw ["Unexpected ", parserState.userQuery[end], " in a string element"];
180180
} else if (start === end) {
181-
throw new Error("Cannot have empty string element");
181+
throw ["Cannot have empty string element"];
182182
}
183183
// To skip the quote at the end.
184184
parserState.pos += 1;
@@ -257,7 +257,7 @@ function initSearch(rawSearchIndex) {
257257
return;
258258
}
259259
if (query.literalSearch && parserState.totalElems - parserState.genericsElems > 0) {
260-
throw new Error("You cannot have more than one element if you use quotes");
260+
throw ["You cannot have more than one element if you use quotes"];
261261
}
262262
const pathSegments = name.split("::");
263263
if (pathSegments.length > 1) {
@@ -266,17 +266,17 @@ function initSearch(rawSearchIndex) {
266266

267267
if (pathSegment.length === 0) {
268268
if (i === 0) {
269-
throw new Error("Paths cannot start with `::`");
269+
throw ["Paths cannot start with ", "::"];
270270
} else if (i + 1 === len) {
271-
throw new Error("Paths cannot end with `::`");
271+
throw ["Paths cannot end with ", "::"];
272272
}
273-
throw new Error("Unexpected `::::`");
273+
throw ["Unexpected ", "::::"];
274274
}
275275
}
276276
}
277277
// In case we only have something like `<p>`, there is no name.
278278
if (pathSegments.length === 0 || (pathSegments.length === 1 && pathSegments[0] === "")) {
279-
throw new Error("Found generics without a path");
279+
throw ["Found generics without a path"];
280280
}
281281
parserState.totalElems += 1;
282282
if (isInGenerics) {
@@ -308,15 +308,15 @@ function initSearch(rawSearchIndex) {
308308
if (!isIdentCharacter(c)) {
309309
if (c === "!") {
310310
if (foundExclamation !== -1) {
311-
throw new Error("Cannot have more than one `!` in an ident");
311+
throw ["Cannot have more than one ", "!", " in an ident"];
312312
} else if (parserState.pos + 1 < parserState.length &&
313313
isIdentCharacter(parserState.userQuery[parserState.pos + 1])
314314
) {
315-
throw new Error("`!` can only be at the end of an ident");
315+
throw ["Unexpected ", "!", ": it can only be at the end of an ident"];
316316
}
317317
foundExclamation = parserState.pos;
318318
} else if (isErrorCharacter(c)) {
319-
throw new Error(`Unexpected \`${c}\``);
319+
throw ["Unexpected ", c];
320320
} else if (
321321
isStopCharacter(c) ||
322322
isSpecialStartCharacter(c) ||
@@ -329,7 +329,7 @@ function initSearch(rawSearchIndex) {
329329
}
330330
if (foundExclamation !== -1) {
331331
if (start <= (end - 2)) {
332-
throw new Error("Cannot have associated items in macros");
332+
throw ["Cannot have associated items in macros"];
333333
} else {
334334
// if start == end - 1, we got the never type
335335
// while the never type has no associated macros, we still
@@ -340,7 +340,7 @@ function initSearch(rawSearchIndex) {
340340
// Skip current ":".
341341
parserState.pos += 1;
342342
} else {
343-
throw new Error(`Unexpected \`${c}\``);
343+
throw ["Unexpected ", c];
344344
}
345345
}
346346
parserState.pos += 1;
@@ -351,8 +351,13 @@ function initSearch(rawSearchIndex) {
351351
if (parserState.typeFilter === null) {
352352
parserState.typeFilter = "macro";
353353
} else if (parserState.typeFilter !== "macro") {
354-
throw new Error("Invalid search type: macro `!` and " +
355-
`\`${parserState.typeFilter}\` both specified`);
354+
throw [
355+
"Invalid search type: macro ",
356+
"!",
357+
" and ",
358+
parserState.typeFilter,
359+
" both specified",
360+
];
356361
}
357362
end = foundExclamation;
358363
}
@@ -382,9 +387,9 @@ function initSearch(rawSearchIndex) {
382387
parserState.userQuery[parserState.pos] === "<"
383388
) {
384389
if (isInGenerics) {
385-
throw new Error("Unexpected `<` after `<`");
390+
throw ["Unexpected ", "<", " after ", "<"];
386391
} else if (start >= end) {
387-
throw new Error("Found generics without a path");
392+
throw ["Found generics without a path"];
388393
}
389394
parserState.pos += 1;
390395
getItemsBefore(query, parserState, generics, ">");
@@ -428,21 +433,39 @@ function initSearch(rawSearchIndex) {
428433
foundStopChar = true;
429434
continue;
430435
} else if (c === ":" && isPathStart(parserState)) {
431-
throw new Error("Unexpected `::`: paths cannot start with `::`");
436+
throw ["Unexpected ", "::", ": paths cannot start with ", "::"];
432437
} else if (c === ":" || isEndCharacter(c)) {
433438
let extra = "";
434439
if (endChar === ">") {
435-
extra = "`<`";
440+
extra = "<";
436441
} else if (endChar === "") {
437-
extra = "`->`";
442+
extra = "->";
443+
} else {
444+
extra = endChar;
438445
}
439-
throw new Error("Unexpected `" + c + "` after " + extra);
446+
throw ["Unexpected ", c, " after ", extra];
440447
}
441448
if (!foundStopChar) {
442449
if (endChar !== "") {
443-
throw new Error(`Expected \`,\`, \` \` or \`${endChar}\`, found \`${c}\``);
450+
throw [
451+
"Expected ",
452+
",", // comma
453+
", ",
454+
"&nbsp;", // whitespace
455+
" or ",
456+
endChar,
457+
", found ",
458+
c,
459+
];
444460
}
445-
throw new Error(`Expected \`,\` or \` \`, found \`${c}\``);
461+
throw [
462+
"Expected ",
463+
",", // comma
464+
" or ",
465+
"&nbsp;", // whitespace
466+
", found ",
467+
c,
468+
];
446469
}
447470
const posBefore = parserState.pos;
448471
getNextElem(query, parserState, elems, endChar === ">");
@@ -470,7 +493,7 @@ function initSearch(rawSearchIndex) {
470493

471494
for (let pos = 0; pos < parserState.pos; ++pos) {
472495
if (!isIdentCharacter(query[pos]) && !isWhitespaceCharacter(query[pos])) {
473-
throw new Error(`Unexpected \`${query[pos]}\` in type filter`);
496+
throw ["Unexpected ", query[pos], " in type filter"];
474497
}
475498
}
476499
}
@@ -496,19 +519,19 @@ function initSearch(rawSearchIndex) {
496519
if (isReturnArrow(parserState)) {
497520
break;
498521
}
499-
throw new Error(`Unexpected \`${c}\` (did you mean \`->\`?)`);
522+
throw ["Unexpected ", c, " (did you mean ", "->", "?)"];
500523
}
501-
throw new Error(`Unexpected \`${c}\``);
524+
throw ["Unexpected ", c];
502525
} else if (c === ":" && !isPathStart(parserState)) {
503526
if (parserState.typeFilter !== null) {
504-
throw new Error("Unexpected `:`");
527+
throw ["Unexpected ", ":"];
505528
}
506529
if (query.elems.length === 0) {
507-
throw new Error("Expected type filter before `:`");
530+
throw ["Expected type filter before ", ":"];
508531
} else if (query.elems.length !== 1 || parserState.totalElems !== 1) {
509-
throw new Error("Unexpected `:`");
532+
throw ["Unexpected ", ":"];
510533
} else if (query.literalSearch) {
511-
throw new Error("You cannot use quotes on type filter");
534+
throw ["You cannot use quotes on type filter"];
512535
}
513536
checkExtraTypeFilterCharacters(parserState);
514537
// The type filter doesn't count as an element since it's a modifier.
@@ -521,9 +544,29 @@ function initSearch(rawSearchIndex) {
521544
}
522545
if (!foundStopChar) {
523546
if (parserState.typeFilter !== null) {
524-
throw new Error(`Expected \`,\`, \` \` or \`->\`, found \`${c}\``);
547+
throw [
548+
"Expected ",
549+
",", // comma
550+
", ",
551+
"&nbsp;", // whitespace
552+
" or ",
553+
"->", // arrow
554+
", found ",
555+
c,
556+
];
525557
}
526-
throw new Error(`Expected \`,\`, \` \`, \`:\` or \`->\`, found \`${c}\``);
558+
throw [
559+
"Expected ",
560+
",", // comma
561+
", ",
562+
"&nbsp;", // whitespace
563+
", ",
564+
":", // colon
565+
" or ",
566+
"->", // arrow
567+
", found ",
568+
c,
569+
];
527570
}
528571
const before = query.elems.length;
529572
getNextElem(query, parserState, query.elems, false);
@@ -540,7 +583,7 @@ function initSearch(rawSearchIndex) {
540583
getItemsBefore(query, parserState, query.returned, "");
541584
// Nothing can come afterward!
542585
if (query.returned.length === 0) {
543-
throw new Error("Expected at least one item after `->`");
586+
throw ["Expected at least one item after ", "->"];
544587
}
545588
break;
546589
} else {
@@ -694,7 +737,7 @@ function initSearch(rawSearchIndex) {
694737
}
695738
} catch (err) {
696739
query = newParsedQuery(userQuery);
697-
query.error = err.message;
740+
query.error = err;
698741
query.typeFilter = -1;
699742
return query;
700743
}
@@ -1760,7 +1803,16 @@ function initSearch(rawSearchIndex) {
17601803

17611804
let output = `<h1 class="search-results-title">Results${crates}</h1>`;
17621805
if (results.query.error !== null) {
1763-
output += `<h3>Query parser error: "${results.query.error}".</h3>`;
1806+
const error = results.query.error;
1807+
error.forEach((value, index) => {
1808+
value = value.split("<").join("&lt;").split(">").join("&gt;");
1809+
if (index % 2 !== 0) {
1810+
error[index] = `<code>${value}</code>`;
1811+
} else {
1812+
error[index] = value;
1813+
}
1814+
});
1815+
output += `<h3 class="error">Query parser error: "${error.join("")}".</h3>`;
17641816
output += "<div id=\"search-tabs\">" +
17651817
makeTabHeader(0, "In Names", ret_others[1]) +
17661818
"</div>";

src/tools/rustdoc-js/tester.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,20 @@ function valueCheck(fullPath, expected, result, error_text, queryName) {
138138
error_text.push('==> Unknown key "' + key + '"');
139139
break;
140140
}
141+
let result_v = result[key];
142+
if (result_v !== null && key === "error") {
143+
result_v.forEach((value, index) => {
144+
value = value.split("&nbsp;").join(" ");
145+
if (index % 2 === 1) {
146+
result_v[index] = "`" + value + "`";
147+
} else {
148+
result_v[index] = value;
149+
}
150+
});
151+
result_v = result_v.join("");
152+
}
141153
const obj_path = fullPath + (fullPath.length > 0 ? '.' : '') + key;
142-
valueCheck(obj_path, expected[key], result[key], error_text, queryName);
154+
valueCheck(obj_path, expected[key], result_v, error_text, queryName);
143155
}
144156
} else {
145157
expectedValue = JSON.stringify(expected);

tests/rustdoc-gui/search-error.goml

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Checks that the crate search filtering is handled correctly and changes the results.
2+
goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=sa'%3Bda'%3Bds"
3+
show-text: true
4+
5+
define-function: (
6+
"check-colors",
7+
(theme, error_background),
8+
block {
9+
// Setting the theme.
10+
local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
11+
// We reload the page so the local storage settings are being used.
12+
reload:
13+
14+
wait-for: "#search .error code"
15+
assert-css: ("#search .error code", {"background-color": |error_background|})
16+
}
17+
)
18+
19+
call-function: (
20+
"check-colors",
21+
{
22+
"theme": "ayu",
23+
"error_background": "rgb(79, 76, 76)",
24+
},
25+
)
26+
call-function: (
27+
"check-colors",
28+
{
29+
"theme": "dark",
30+
"error_background": "rgb(72, 72, 72)",
31+
},
32+
)
33+
call-function: (
34+
"check-colors",
35+
{
36+
"theme": "light",
37+
"error_background": "rgb(208, 204, 204)",
38+
},
39+
)

0 commit comments

Comments
 (0)