From b86812e92cd80ea4e68dd603cf376ead35439492 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Mon, 10 Aug 2026 20:25:56 +0200 Subject: [PATCH 1/2] feat(text): read a text file in a quieter gutter The text view was the last one still on its first styling: a browser default monospace against a three-pixel grey rule, no page padding, and line numbers that drifted off their lines the further down the file you read - the script sizing the number cells rounded a fractional line height per cell. Restyle it against the palette the xml, filesystem and sheet views already use, pin the line height to a whole pixel, measure the lines with `getBoundingClientRect`, keep the numbers out of a selection of the page, and mark the hovered line across both columns. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01SJYhr3t6QBamsHRfZ7gPDw --- CHANGELOG.md | 2 ++ src/odr/internal/html/frontend.cpp | 30 ++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb95cb34..4d8150ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ The release run heads these entries with the version and opens a fresh rather than as one very long line, in the encoding its declaration names. - An svg is recognised by reading it rather than by what it is called, so bytes that are not one no longer open as an image that cannot be shown. +- A text file reads in a quieter gutter: the line numbers line up with their + lines, stay out of a copy of the page, and the hovered line is marked. ## v6.4.0 - 2026-08-09 diff --git a/src/odr/internal/html/frontend.cpp b/src/odr/internal/html/frontend.cpp index a6ab7400..83a02fc4 100644 --- a/src/odr/internal/html/frontend.cpp +++ b/src/odr/internal/html/frontend.cpp @@ -80,11 +80,30 @@ td x-p{height:inherit} .odr-sheet-sort-asc::after{content:"\25B4"} )css"; +/// A whole-pixel line height, because the line numbers are a second column +/// whose cells are sized to the lines by script - a fractional line would round +/// per cell and the two columns would drift apart. constexpr std::string_view text_css = R"css( -.odr-text{display:flex;flex-direction:row;font-family:monospace} -.odr-text-nr{display:flex;flex-direction:column;text-align:right;vertical-align:top;color:#999;border-right:solid #999} -.odr-text-body{display:flex;flex-direction:column;padding-left:5pt;white-space:pre} +:root{ +--odr-text-fg:#1f2328; +--odr-text-muted:#8c959f; +--odr-text-line:#d8dee4; +--odr-text-gutter:#f6f8fa; +--odr-text-wash:rgba(0,0,0,.04); +--odr-text-mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; +} +body{margin:0;background:#fff} +.odr-text{display:flex;align-items:stretch;min-height:100vh;color:var(--odr-text-fg);font:13px/20px var(--odr-text-mono);tab-size:4} +/* The numbers are ours, not the file's, so the gutter stays out of a selection + of the page. */ +.odr-text-nr{display:flex;flex-direction:column;flex:none;padding:16px 12px 16px 16px;text-align:right;color:var(--odr-text-muted);background:var(--odr-text-gutter);border-right:1px solid var(--odr-text-line);font-variant-numeric:tabular-nums;user-select:none;-webkit-user-select:none} +.odr-text-body{display:flex;flex-direction:column;flex:1;min-width:0;padding:16px;white-space:pre} .odr-text-wrap{white-space:break-spaces;word-break:break-word;overflow-wrap:anywhere} +/* A hovered line reaches its number, which is in the other column, by beginning + a viewport to the left of it; the padding puts the text back where it was. + Overflow to the left of the page does not scroll. */ +.odr-text-body>div{margin-left:-100vw;padding-left:100vw} +.odr-text-body>div:hover{background:var(--odr-text-wash)} [contenteditable]:focus{outline:none} )css"; @@ -641,11 +660,14 @@ constexpr std::string_view text_js = R"js( }); } + // The measured height is fractional; `offsetHeight` would round it per line + // and the numbers would walk away from the lines they belong to. TextEditor.prototype.updateLineNumberHeight = function () { var nrCells = this.textNr.querySelectorAll("div"); var textCells = this.textBody.querySelectorAll("div"); for (var i = 0; i < textCells.length && i < nrCells.length; ++i) { - nrCells[i].style.height = textCells[i].offsetHeight + "px"; + nrCells[i].style.height = + textCells[i].getBoundingClientRect().height + "px"; } }; From 41d766105b50d44c7dfb81745ca971ddbffa7048 Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Mon, 10 Aug 2026 20:35:55 +0200 Subject: [PATCH 2/2] feat(html): let a page set its own body margin and background Every view but the pdf one and the text one read the browser's default sheet for the body box, so a file listing, a source view or an image opened inset by an eight-pixel white border nobody had asked for. Each stylesheet now states `body{margin:0;background:...}` itself - spelled out even where `*{margin:0}` already covered it - and the image and font pages, which shipped no body rule at all, get one. The xml view takes the space back as padding on its own container; the font specimen keeps its eight pixels, now as padding of its own. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01SJYhr3t6QBamsHRfZ7gPDw --- CHANGELOG.md | 2 ++ src/odr/internal/html/font_file.cpp | 4 +++- src/odr/internal/html/frontend.cpp | 14 +++++++++----- src/odr/internal/html/image_file.cpp | 3 +++ test/data.cmake | 2 +- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d8150ad..b5fc0d3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ The release run heads these entries with the version and opens a fresh that are not one no longer open as an image that cannot be shown. - A text file reads in a quieter gutter: the line numbers line up with their lines, stay out of a copy of the page, and the hovered line is marked. +- Every page states its own body margin and background instead of inheriting the + browser's, so no view opens inset by an eight-pixel border. ## v6.4.0 - 2026-08-09 diff --git a/src/odr/internal/html/font_file.cpp b/src/odr/internal/html/font_file.cpp index 4b052178..ffb6baa3 100644 --- a/src/odr/internal/html/font_file.cpp +++ b/src/odr/internal/html/font_file.cpp @@ -110,7 +110,9 @@ class HtmlServiceImpl final : public HtmlService { out.out() << "