Dynamic width of code box line numbers
authorAlexander Ebert <ebert@woltlab.com>
Sun, 15 May 2022 10:37:51 +0000 (12:37 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sun, 15 May 2022 10:37:51 +0000 (12:37 +0200)
This avoids indenting short code listings too much, especially on screens with limited space.

ts/WoltLabSuite/Core/Bbcode/Code.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Bbcode/Code.js
wcfsetup/install/files/style/bbcode/code.scss

index f8d15479429550a1caa4cc594c3adfb518cc8585..4ec1e507bbd96f9a212266eddd852c4858bdfb0b 100644 (file)
@@ -37,6 +37,8 @@ class Code {
     this.language = Array.from(this.codeContainer.classList)
       .find((klass) => /^language-([a-z0-9_-]+)$/.test(klass))
       ?.replace(/^language-/, "");
+
+    this.calculateLineNumberWidth();
   }
 
   public static processAll(): void {
@@ -132,6 +134,27 @@ class Code {
     this.container.classList.remove("highlighting");
     this.container.classList.add("highlighted");
   }
+
+  private calculateLineNumberWidth(): void {
+    if (!this.codeContainer) {
+      return;
+    }
+
+    let maxLength = 0;
+    this.codeContainer.querySelectorAll(".lineAnchor").forEach((anchor: HTMLAnchorElement) => {
+      const length = anchor.title.length;
+      if (length > maxLength) {
+        maxLength = length;
+      }
+    });
+
+    // Clamp the max length to 6 (up to line 999,999) to prevent layout issues.
+    if (maxLength > 6) {
+      maxLength = 6;
+    }
+
+    this.container.style.setProperty("--line-number-width", maxLength.toString());
+  }
 }
 
 export = Code;
index b42f4b792a5085fead356c36c589e4e41ab91aad..3bfd0f3228cdfc63530d5039e3604aeefe73f374 100644 (file)
@@ -30,6 +30,7 @@ define(["require", "exports", "tslib", "../Language", "../Clipboard", "../Ui/Not
             this.codeContainer = this.container.querySelector(".codeBoxCode > code");
             this.language = (_a = Array.from(this.codeContainer.classList)
                 .find((klass) => /^language-([a-z0-9_-]+)$/.test(klass))) === null || _a === void 0 ? void 0 : _a.replace(/^language-/, "");
+            this.calculateLineNumberWidth();
         }
         static processAll() {
             document.querySelectorAll(".codeBox:not([data-processed])").forEach((codeBox) => {
@@ -101,6 +102,23 @@ define(["require", "exports", "tslib", "../Language", "../Clipboard", "../Ui/Not
             this.container.classList.remove("highlighting");
             this.container.classList.add("highlighted");
         }
+        calculateLineNumberWidth() {
+            if (!this.codeContainer) {
+                return;
+            }
+            let maxLength = 0;
+            this.codeContainer.querySelectorAll(".lineAnchor").forEach((anchor) => {
+                const length = anchor.title.length;
+                if (length > maxLength) {
+                    maxLength = length;
+                }
+            });
+            // Clamp the max length to 6 (up to line 999,999) to prevent layout issues.
+            if (maxLength > 6) {
+                maxLength = 6;
+            }
+            this.container.style.setProperty("--line-number-width", maxLength.toString());
+        }
     }
     Code.chunkSize = 50;
     return Code;
index 4cee52faaa202d539c46b408ab2553872aca5c60..f6e80f71aced3d5a849e1eaef4a06b64d71eb492 100644 (file)
 
        .codeBoxCode {
                position: relative;
-               padding-left: 7ch;
+               padding-left: calc((var(--line-number-width, 6) + 1) * 1ch);
 
                > code {
                        display: block;
                                display: block;
 
                                > a {
-                                       margin-left: -7ch;
+                                       margin-left: calc((var(--line-number-width, 6) + 1) * -1ch);
                                        overflow: hidden;
                                        position: absolute;
                                        text-align: right;
                                        text-overflow: ellipsis;
                                        white-space: nowrap;
-                                       /* No one has line numbers greater than 999999 */
-                                       width: 6ch;
+                                       width: calc(var(--line-number-width, 6) * 1ch);
 
                                        &::before {
                                                content: attr(title);