Skip to content

[rustdoc] Add new setting to wrap source code lines when too long #136991

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 66 additions & 41 deletions src/librustdoc/html/static/css/rustdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ xmlns="http://www.w3.org/2000/svg" fill="black" height="18px">\
--font-family: "Source Serif 4", NanumBarunGothic, serif;
--font-family-code: "Source Code Pro", monospace;
--line-number-padding: 4px;
--line-number-right-margin: 20px;
/* scraped examples icons (34x33px) */
--prev-arrow-image: url('data:image/svg+xml,<svg width="16" height="16" viewBox="0 0 16 16" \
enable-background="new 0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path fill="none" \
Expand Down Expand Up @@ -848,22 +849,6 @@ ul.block, .block li, .block ul {
border-radius: 6px;
}

/*
If the code example line numbers are displayed, there will be a weird radius in the middle from
both the code example and the line numbers, so we need to remove the radius in this case.
*/
.rustdoc .example-wrap > .example-line-numbers,
.rustdoc .scraped-example .src-line-numbers,
.rustdoc .scraped-example .src-line-numbers > pre {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.rustdoc .example-wrap > .example-line-numbers + pre,
.rustdoc .scraped-example .rust {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}

.rustdoc .scraped-example {
position: relative;
}
Expand Down Expand Up @@ -908,65 +893,105 @@ both the code example and the line numbers, so we need to remove the radius in t
overflow: auto;
}

.rustdoc .example-wrap pre.example-line-numbers,
.rustdoc .example-wrap .src-line-numbers {
min-width: fit-content; /* prevent collapsing into nothing in truncated scraped examples */
flex-grow: 0;
text-align: right;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
padding: 14px 8px;
padding-right: 2px;
color: var(--src-line-numbers-span-color);
}

.example-wrap.digits-1 [data-nosnippet] {
.example-wrap.digits-1:not(.hide-lines) [data-nosnippet] {
width: calc(1ch + var(--line-number-padding) * 2);
}
.example-wrap.digits-2 [data-nosnippet] {
.example-wrap.digits-2:not(.hide-lines) [data-nosnippet] {
width: calc(2ch + var(--line-number-padding) * 2);
}
.example-wrap.digits-3 [data-nosnippet] {
.example-wrap.digits-3:not(.hide-lines) [data-nosnippet] {
width: calc(3ch + var(--line-number-padding) * 2);
}
.example-wrap.digits-4 [data-nosnippet] {
.example-wrap.digits-4:not(.hide-lines) [data-nosnippet] {
width: calc(4ch + var(--line-number-padding) * 2);
}
.example-wrap.digits-5 [data-nosnippet] {
.example-wrap.digits-5:not(.hide-lines) [data-nosnippet] {
width: calc(5ch + var(--line-number-padding) * 2);
}
.example-wrap.digits-6 [data-nosnippet] {
.example-wrap.digits-6:not(.hide-lines) [data-nosnippet] {
width: calc(6ch + var(--line-number-padding) * 2);
}
.example-wrap.digits-7 [data-nosnippet] {
.example-wrap.digits-7:not(.hide-lines) [data-nosnippet] {
width: calc(7ch + var(--line-number-padding) * 2);
}
.example-wrap.digits-8 [data-nosnippet] {
.example-wrap.digits-8:not(.hide-lines) [data-nosnippet] {
width: calc(8ch + var(--line-number-padding) * 2);
}
.example-wrap.digits-9 [data-nosnippet] {
.example-wrap.digits-9:not(.hide-lines) [data-nosnippet] {
width: calc(9ch + var(--line-number-padding) * 2);
}

.example-wrap [data-nosnippet] {
color: var(--src-line-numbers-span-color);
text-align: right;
display: inline-block;
margin-right: 20px;
margin-right: var(--line-number-right-margin);
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
padding: 0 4px;
padding: 0 var(--line-number-padding);
}
.example-wrap [data-nosnippet]:target {
border-right: none;
}
.example-wrap .line-highlighted[data-nosnippet] {
background-color: var(--src-line-number-highlighted-background-color);
}
:root.word-wrap-source-code .example-wrap [data-nosnippet] {
position: absolute;
left: 0;
}
.word-wrap-source-code .example-wrap pre > code {
position: relative;
word-break: break-all;
}
:root.word-wrap-source-code .example-wrap pre > code {
display: block;
white-space: pre-wrap;
}
:root.word-wrap-source-code .example-wrap pre > code * {
word-break: break-all;
}
:root.word-wrap-source-code .example-wrap.digits-1 pre > code {
padding-left: calc(
1ch + var(--line-number-padding) * 2 + var(--line-number-right-margin));
}
:root.word-wrap-source-code .example-wrap.digits-2 pre > code {
padding-left: calc(
2ch + var(--line-number-padding) * 2 + var(--line-number-right-margin));
}
:root.word-wrap-source-code .example-wrap.digits-3 pre > code {
padding-left: calc(
3ch + var(--line-number-padding) * 2 + var(--line-number-right-margin));
}
:root.word-wrap-source-code .example-wrap.digits-4 pre > code {
padding-left: calc(
4ch + var(--line-number-padding) * 2 + var(--line-number-right-margin));
}
:root.word-wrap-source-code .example-wrap.digits-5 pre > code {
padding-left: calc(
5ch + var(--line-number-padding) * 2 + var(--line-number-right-margin));
}
:root.word-wrap-source-code .example-wrap.digits-6 pre > code {
padding-left: calc(
6ch + var(--line-number-padding) * 2 + var(--line-number-right-margin));
}
:root.word-wrap-source-code .example-wrap.digits-7 pre > code {
padding-left: calc(
7ch + var(--line-number-padding) * 2 + var(--line-number-right-margin));
}
:root.word-wrap-source-code .example-wrap.digits-8 pre > code {
padding-left: calc(
8ch + var(--line-number-padding) * 2 + var(--line-number-right-margin));
}
:root.word-wrap-source-code .example-wrap.digits-9 pre > code {
padding-left: calc(
9ch + var(--line-number-padding) * 2 + var(--line-number-right-margin));
}
.example-wrap.hide-lines [data-nosnippet] {
display: none;
}

.search-loading {
text-align: center;
Expand Down
37 changes: 17 additions & 20 deletions src/librustdoc/html/static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -1112,35 +1112,32 @@ function preLoadCss(cssUrl) {

// @ts-expect-error
window.rustdoc_add_line_numbers_to_examples = () => {
if (document.querySelector(".rustdoc.src")) {
// We are in the source code page, nothing to be done here!
return;
// @ts-expect-error
function generateLine(nb) {
return `<span data-nosnippet>${nb}</span>`;
}

onEachLazy(document.querySelectorAll(
":not(.scraped-example) > .example-wrap > pre:not(.example-line-numbers)",
), x => {
const parent = x.parentNode;
const line_numbers = parent.querySelectorAll(".example-line-numbers");
if (line_numbers.length > 0) {
".rustdoc:not(.src) :not(.scraped-example) > .example-wrap > pre > code",
), code => {
if (hasClass(code.parentElement.parentElement, "hide-lines")) {
removeClass(code.parentElement.parentElement, "hide-lines");
return;
}
const count = x.textContent.split("\n").length;
const elems = [];
for (let i = 0; i < count; ++i) {
elems.push(i + 1);
}
const node = document.createElement("pre");
addClass(node, "example-line-numbers");
node.innerHTML = elems.join("\n");
parent.insertBefore(node, x);
const lines = code.innerHTML.split("\n");
const digits = (lines.length + "").length;
// @ts-expect-error
code.innerHTML = lines.map((line, index) => generateLine(index + 1) + line).join("\n");
addClass(code.parentElement.parentElement, `digits-${digits}`);
});
};

// @ts-expect-error
window.rustdoc_remove_line_numbers_from_examples = () => {
onEachLazy(document.querySelectorAll(".example-wrap > .example-line-numbers"), x => {
x.parentNode.removeChild(x);
});
onEachLazy(
document.querySelectorAll(".rustdoc:not(.src) :not(.scraped-example) > .example-wrap"),
x => addClass(x, "hide-lines"),
);
};

if (getSettingValue("line-numbers") === "true") {
Expand Down
13 changes: 13 additions & 0 deletions src/librustdoc/html/static/js/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@
} else {
removeClass(document.documentElement, "sans-serif");
}
break;
case "word-wrap-source-code":
if (value === true) {
addClass(document.documentElement, "word-wrap-source-code");
} else {
removeClass(document.documentElement, "word-wrap-source-code");
}
break;
}
}

Expand Down Expand Up @@ -246,6 +254,11 @@
"js_name": "sans-serif-fonts",
"default": false,
},
{
"name": "Word wrap source code",
"js_name": "word-wrap-source-code",
"default": false,
},
];

// Then we build the DOM.
Expand Down
3 changes: 3 additions & 0 deletions src/librustdoc/html/static/js/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ if (getSettingValue("hide-modnav") === "true") {
if (getSettingValue("sans-serif-fonts") === "true") {
addClass(document.documentElement, "sans-serif");
}
if (getSettingValue("word-wrap-source-code") === "true") {
addClass(document.documentElement, "word-wrap-source-code");
}
function updateSidebarWidth() {
const desktopSidebarWidth = getSettingValue("desktop-sidebar-width");
if (desktopSidebarWidth && desktopSidebarWidth !== "null") {
Expand Down
68 changes: 16 additions & 52 deletions tests/rustdoc-gui/docblock-code-block-line-number.goml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ assert-css: (
set-local-storage: {"rustdoc-line-numbers": "true"}
reload:
// We wait for the line numbers to be added into the DOM by the JS...
wait-for: "pre.example-line-numbers"
wait-for: ".digits-1 pre"

// Otherwise, we can't check text color
show-text: true
Expand All @@ -35,30 +35,21 @@ define-function: (
call-function: ("switch-theme", {"theme": |theme|})
// If the test didn't fail, it means that it was found!
assert-css: (
"pre.example-line-numbers",
".digits-1 pre [data-nosnippet]",
{
"color": |color|,
"margin": "0px",
"padding-top": "14px",
"padding-bottom": "14px",
"padding-left": "8px",
"padding-right": "2px",
"margin-top": "0px",
"margin-bottom": "0px",
"margin-left": "0px",
"margin-right": "20px",
"padding-top": "0px",
"padding-bottom": "0px",
"padding-left": "4px",
"padding-right": "4px",
"text-align": "right",
// There should not be a radius on the right of the line numbers.
"border-top-left-radius": "6px",
"border-bottom-left-radius": "6px",
"border-top-right-radius": "0px",
"border-bottom-right-radius": "0px",
},
ALL,
)
// There should not be a radius on the left of the line numbers.
assert-css: ("pre.example-line-numbers + .rust", {
"border-top-left-radius": "0px",
"border-bottom-left-radius": "0px",
"border-top-right-radius": "6px",
"border-bottom-right-radius": "6px",
})
},
)
call-function: ("check-colors", {
Expand All @@ -74,9 +65,6 @@ call-function: ("check-colors", {
"color": "#c67e2d",
})

// The first code block has two lines so let's check its `<pre>` elements lists both of them.
assert-text: ("pre.example-line-numbers", "1\n2")

// Now, try changing the setting dynamically. We'll turn it off, using the settings menu,
// and make sure it goes away.

Expand All @@ -87,42 +75,17 @@ assert-css: ("#settings", {"display": "block"})

// Then, click the toggle button.
click: "input#line-numbers"
wait-for-false: "pre.example-line-numbers"
wait-for: ".digits-1.hide-lines"
assert-local-storage: {"rustdoc-line-numbers": "false" }

// Check that the rounded corners are back.
assert-css: (
".example-wrap .rust",
{
"border-top-left-radius": "6px",
"border-bottom-left-radius": "6px",
"border-top-right-radius": "6px",
"border-bottom-right-radius": "6px",
},
ALL,
)

// Finally, turn it on again.
click: "input#line-numbers"
wait-for: "pre.example-line-numbers"
wait-for: ".digits-1:not(.hide-lines)"
assert-local-storage: {"rustdoc-line-numbers": "true" }
wait-for: "pre.example-line-numbers"

// Same check with scraped examples line numbers.
go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"

assert-css: (
".scraped-example .rust",
{
// There should not be a radius on the left of the code.
"border-top-left-radius": "0px",
"border-bottom-left-radius": "0px",
"border-top-right-radius": "6px",
"border-bottom-right-radius": "6px",
},
ALL,
)

define-function: (
"check-padding",
[path, padding_bottom],
Expand Down Expand Up @@ -203,17 +166,18 @@ assert-local-storage: {"rustdoc-line-numbers": "true" }
assert: ".example-wrap > pre.language-txt"
assert: ".example-wrap > pre.rust"
assert-count: (".example-wrap", 2)
assert-count: (".example-wrap > pre.example-line-numbers", 2)
assert-count: (".example-wrap.digits-1", 2)

click: "#settings-menu"
wait-for: "#settings"

// Then, click the toggle button.
click: "input#line-numbers"
wait-for-count: (".example-wrap > pre.example-line-numbers", 0)
wait-for-count: (".example-wrap.digits-1.hide-lines", 2)
assert-local-storage-false: {"rustdoc-line-numbers": "true" }

// Now turning off the setting.
click: "input#line-numbers"
wait-for-count: (".example-wrap > pre.example-line-numbers", 2)
wait-for-count: (".example-wrap.digits-1", 2)
wait-for-count: (".example-wrap.digits-1.hide-lines", 0)
assert-local-storage: {"rustdoc-line-numbers": "true" }
Loading
Loading