refactor(web): replace :global(.line) with CSS module scoped class
Quentin Gliech
and
Claude Opus 4.6 (1M context)
created 1 month ago
Use a Shiki transformer to replace the default "line" class with our
CSS module's scoped .line class. No more :global() needed — everything
is properly module-scoped.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change summary
webui2/src/components/code/file-viewer.module.css | 8 ++++----
webui2/src/components/code/file-viewer.tsx | 10 ++++++----
2 files changed, 10 insertions(+), 8 deletions(-)
Detailed changes
@@ -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;
@@ -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 <style>{`${rule}{background-color:rgba(255,235,59,0.3)}:root.dark ${rule}{background-color:rgba(255,235,59,0.15)}`}</style>;