diff --git a/webui2/src/components/code/file-viewer.module.css b/webui2/src/components/code/file-viewer.module.css index 49f4cb392e3a8ce63ce4eec824987ff39217cbb2..ee4b6baa72702fb061a2ec1eae0c8e96f239191c 100644 --- a/webui2/src/components/code/file-viewer.module.css +++ b/webui2/src/components/code/file-viewer.module.css @@ -14,22 +14,22 @@ display: block; } -.code-content code > :global(.line) { +.line { display: block; min-width: 100%; padding-right: 1rem; } -.code-content code > :global(.line):first-child { +.line:first-child { padding-top: 0.5rem; } -.code-content code > :global(.line):last-child { +.line:last-child { padding-bottom: 0.5rem; } /* Line numbers via ::before pseudo-element */ -.code-content code > :global(.line)::before { +.line::before { content: attr(data-line-number); display: inline-block; width: 3rem; diff --git a/webui2/src/components/code/file-viewer.tsx b/webui2/src/components/code/file-viewer.tsx index c63d9cf727d523f257607a2a356ff7cab7e84784..97bcb569b8af5fa6aacd3d42c2c02a71d607cc1a 100644 --- a/webui2/src/components/code/file-viewer.tsx +++ b/webui2/src/components/code/file-viewer.tsx @@ -94,13 +94,15 @@ function getLangEntry(path: string): LangEntry | undefined { function lineNumberTransformer(): ShikiTransformer { return { line(node, line) { + // Replace Shiki's "line" class with our CSS module class + node.properties["className"] = [styles["line"]!]; node.properties["dataLineNumber"] = line; - // Append a \n text node inside each .line so copy-paste preserves newlines + // Append a \n text node so copy-paste preserves newlines // (we strip the inter-element whitespace nodes in code() below). node.children.push({ type: "text", value: "\n" }); }, // Remove whitespace text nodes between .line spans — they create - // empty anonymous table rows when using display: table-row. + // empty anonymous rows when using display: block. code(node) { node.children = node.children.filter( (c) => !(c.type === "text" && c.value.trim() === ""), @@ -289,10 +291,10 @@ function CodeBlock({ selectedRange, onLineClick, children }: CodeBlockProps) { // targeting the CSS module's scoped class. const highlightStyle = (() => { if (!selectedRange) return null; - const scope = `.${styles["code-content"]}`; + const lineClass = styles["line"]; const selectors: string[] = []; for (let i = selectedRange.start; i <= selectedRange.end; i++) { - selectors.push(`${scope} code > .line:nth-child(${i})`); + selectors.push(`.${lineClass}:nth-child(${i})`); } const rule = selectors.join(","); return ;