diff --git a/src/renderer/renderer.ts b/src/renderer/renderer.ts
index 4e0b708..e0ef6ea 100644
--- a/src/renderer/renderer.ts
+++ b/src/renderer/renderer.ts
@@ -1635,7 +1635,7 @@ function secondaryRenderVisibleLines(sv: SecondaryViewerInstance): void {
div.className = className;
div.dataset.lineNumber = String(line.lineNumber);
- const lineNumHtml = `${line.lineNumber + 1}`;
+ const lineNumHtml = ``;
const contentHtml = `${escapeHtml(line.text)}`;
div.innerHTML = lineNumHtml + contentHtml;
@@ -2927,7 +2927,7 @@ function createLineElementPooled(line: LogLine): HTMLDivElement {
if (isLineMuted(line.text)) div.classList.add('muted');
// Create content using innerHTML for speed (single parse)
- const lineNumHtml = `${line.lineNumber + 1}`;
+ const lineNumHtml = ``;
let displayText = applyColumnFilter(line.text);
// Truncate very long lines to prevent DOM/rendering slowness
@@ -2994,7 +2994,7 @@ function createPlaceholderLinePooled(displayIndex: number): HTMLDivElement {
div.dataset.lineNumber = '';
const numHtml = state.isFiltered
? ''
- : `${displayIndex + 1}`;
+ : ``;
// Dim inline bar (currentColor adapts to the theme); width jittered by index so
// the skeleton reads as text, not a solid block.
const barWidth = 30 + (displayIndex % 7) * 8; // 30–78%
@@ -3032,7 +3032,9 @@ function createLineElement(line: LogLine): HTMLDivElement {
const lineNumSpan = document.createElement('span');
lineNumSpan.className = 'line-number';
- lineNumSpan.textContent = String(line.lineNumber + 1);
+ // Render the number via CSS ::before (data-lineno) so it's NOT real DOM text and can't
+ // be selected/copied — copying a section yields the log text only, no line numbers.
+ lineNumSpan.setAttribute('data-lineno', String(line.lineNumber + 1));
const contentSpan = document.createElement('span');
contentSpan.className = 'line-content';
diff --git a/src/renderer/styles.css b/src/renderer/styles.css
index d50bc79..cd8007c 100644
--- a/src/renderer/styles.css
+++ b/src/renderer/styles.css
@@ -2668,11 +2668,19 @@ button.is-cancelable:hover, .btn.is-cancelable:hover { filter: brightness(1.12);
color: var(--text-muted);
text-align: right;
padding-right: 15px;
+ -webkit-user-select: none;
user-select: none;
border-right: 1px solid var(--border-color);
margin-right: 10px;
}
+/* Show the number as CSS-generated content (data-lineno) rather than real text, so
+ selecting/copying a section of the log NEVER includes the line numbers. Uses ::after
+ so it doesn't collide with the diff view's ::before +/-/~ gutter markers below. */
+.line-number::after {
+ content: attr(data-lineno);
+}
+
.line-content {
flex: 1;
user-select: text;