From da6f15aa1d6708dacdbc3e63466e81dc3492138d Mon Sep 17 00:00:00 2001 From: Bogdan Date: Fri, 13 Mar 2026 22:41:13 +0100 Subject: [PATCH 1/7] fix: wrap lines and compute width --- app/components/Code/Viewer.vue | 115 ++++++++++-------- .../v/[version]/[...filePath].vue | 23 +++- 2 files changed, 82 insertions(+), 56 deletions(-) diff --git a/app/components/Code/Viewer.vue b/app/components/Code/Viewer.vue index 90bcf0c221..ab27fed728 100644 --- a/app/components/Code/Viewer.vue +++ b/app/components/Code/Viewer.vue @@ -86,11 +86,10 @@ watch( + + From 6955710074c0996dce16ec15295a0038104c804d Mon Sep 17 00:00:00 2001 From: Bogdan Date: Fri, 13 Mar 2026 22:50:41 +0100 Subject: [PATCH 2/7] chore: revert to non-nested css --- app/components/Code/Viewer.vue | 102 ++++++++++++++++----------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/app/components/Code/Viewer.vue b/app/components/Code/Viewer.vue index ab27fed728..bd0f304780 100644 --- a/app/components/Code/Viewer.vue +++ b/app/components/Code/Viewer.vue @@ -135,57 +135,57 @@ watch( flex: 1; min-width: 0; max-width: calc(100% - var(--line-numbers-width)); +} + +.code-content:deep(pre) { + margin: 0; + padding: 0; + background: transparent !important; + overflow: visible; + max-width: 100%; +} + +.code-content:deep(code) { + display: block; + padding: 0 1rem; + background: transparent !important; + max-width: 100%; +} + +.code-content:deep(.line) { + display: flex; + flex-wrap: wrap; + /* Ensure consistent height matching line numbers */ + line-height: 24px; + min-height: 24px; + white-space: pre-wrap; + overflow: hidden; + transition: background-color 0.1s; + max-width: 100%; +} + +/* Highlighted lines in code content - extend full width with negative margin */ +.code-content:deep(.line.highlighted) { + @apply bg-yellow-500/20; + margin: 0 -1rem; + padding: 0 1rem; +} + +/* Clickable import links */ +.code-content:deep(.import-link) { + color: inherit; + text-decoration: underline; + text-decoration-style: dotted; + text-decoration-color: rgba(158, 203, 255, 0.5); /* syntax.str with transparency */ + text-underline-offset: 2px; + transition: + text-decoration-color 0.15s, + text-decoration-style 0.15s; + cursor: pointer; +} - &:deep(pre) { - margin: 0; - padding: 0; - background: transparent !important; - overflow: visible; - max-width: 100%; - } - - &:deep(code) { - display: block; - padding: 0 1rem; - background: transparent !important; - max-width: 100%; - } - - &:deep(.line) { - display: flex; - flex-wrap: wrap; - /* Ensure consistent height matching line numbers */ - line-height: 24px; - min-height: 24px; - white-space: pre-wrap; - overflow: hidden; - transition: background-color 0.1s; - max-width: 100%; - } - - /* Highlighted lines in code content - extend full width with negative margin */ - &:deep(.line.highlighted) { - @apply bg-yellow-500/20; - margin: 0 -1rem; - padding: 0 1rem; - } - - /* Clickable import links */ - &:deep(.import-link) { - color: inherit; - text-decoration: underline; - text-decoration-style: dotted; - text-decoration-color: rgba(158, 203, 255, 0.5); /* syntax.str with transparency */ - text-underline-offset: 2px; - transition: - text-decoration-color 0.15s, - text-decoration-style 0.15s; - cursor: pointer; - } - - &:deep(.import-link:hover) { - text-decoration-style: solid; - text-decoration-color: #9ecbff; /* syntax.str - light blue */ - } +.code-content:deep(.import-link:hover) { + text-decoration-style: solid; + text-decoration-color: #9ecbff; /* syntax.str - light blue */ } From 9e08913fa74354256b4cf462ef5c9d71443637d5 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Fri, 13 Mar 2026 22:52:40 +0100 Subject: [PATCH 3/7] fix: Fix @screen usage --- .../[packageName]/v/[version]/[...filePath].vue | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue b/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue index db41ab7455..fe78e55386 100644 --- a/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue +++ b/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue @@ -588,16 +588,17 @@ defineOgImageComponent('Default', { From a6e9ca5c6e2bcc6b267a46808480e982bfcecc16 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Fri, 13 Mar 2026 22:53:53 +0100 Subject: [PATCH 4/7] fix: 100vw calculation err --- .../[[org]]/[packageName]/v/[version]/[...filePath].vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue b/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue index fe78e55386..5d3fb67dd4 100644 --- a/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue +++ b/app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue @@ -599,6 +599,6 @@ defineOgImageComponent('Default', { width: var(--sidebar-space); } .file-viewer { - width: calc(100vw - var(--sidebar-space)); + width: calc(100% - var(--sidebar-space)); } From f62fefeeccf774c098b0b2d285303b8185fcb1eb Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 15 Mar 2026 06:00:25 +0100 Subject: [PATCH 5/7] fix: track line digits as well --- app/components/Code/Viewer.vue | 69 ++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/app/components/Code/Viewer.vue b/app/components/Code/Viewer.vue index bd0f304780..5e924f27e6 100644 --- a/app/components/Code/Viewer.vue +++ b/app/components/Code/Viewer.vue @@ -11,16 +11,37 @@ const emit = defineEmits<{ const codeRef = useTemplateRef('codeRef') -// Generate line numbers array -const lineNumbers = computed(() => { - return Array.from({ length: props.lines }, (_, i) => i + 1) -}) +// Using this so we can track the height of each line, and therefore compute digit sidebar +const lineMultipliers = ref([]) -// Used for CSS calculation of line number column width -const lineDigits = computed(() => { - return String(props.lines).length +function updateLineMultipliers() { + if (!codeRef.value) return + const lines = Array.from(codeRef.value.querySelectorAll('code > .line')) + lineMultipliers.value = lines + .map(line => Math.round(parseFloat(getComputedStyle(line).height) / 24)) // since each line "row" is 24px high + .filter(m => m > 0) +} + +watch( + () => props.html, + () => nextTick(updateLineMultipliers), + { immediate: true }, +) +useResizeObserver(codeRef, updateLineMultipliers) + +// Line numbers ++ blank rows for the wrapped lines +const displayLines = computed(() => { + const result: (number | null)[] = [] + for (let i = 0; i < props.lines; i++) { + result.push(i + 1) + const extra = (lineMultipliers.value[i] ?? 1) - 1 + for (let j = 0; j < extra; j++) result.push(null) + } + return result }) +const lineDigits = computed(() => String(props.lines).length) + // Check if a line is selected function isLineSelected(lineNum: number): boolean { if (!props.selectedLines) return false @@ -93,22 +114,24 @@ watch( aria-hidden="true" > - - {{ lineNum }} - + From 81c79a9d867f12995db9d90c892f930f8c306dfd Mon Sep 17 00:00:00 2001 From: "jyc.dev" Date: Sat, 14 Mar 2026 06:28:51 +0100 Subject: [PATCH 6/7] fix: always align weekly chart buckets from range end date (#2071) --- app/utils/chart-data-buckets.ts | 12 ++++-------- test/unit/app/utils/chart-data-buckets.spec.ts | 12 ++++++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/utils/chart-data-buckets.ts b/app/utils/chart-data-buckets.ts index 1165c4541f..1cc4a43308 100644 --- a/app/utils/chart-data-buckets.ts +++ b/app/utils/chart-data-buckets.ts @@ -34,17 +34,13 @@ export function buildWeeklyEvolution( if (sorted.length === 0) return [] const rangeStartDate = parseIsoDate(rangeStartIso) + const rangeEndDate = parseIsoDate(rangeEndIso) - // Align from last day with actual data (npm has 1-2 day delay, today is incomplete) - const lastNonZero = sorted.findLast(d => d.value > 0) - const pickerEnd = parseIsoDate(rangeEndIso) - const effectiveEnd = lastNonZero ? parseIsoDate(lastNonZero.day) : pickerEnd - const rangeEndDate = effectiveEnd.getTime() < pickerEnd.getTime() ? effectiveEnd : pickerEnd - - // Group into 7-day buckets from END backwards const buckets = new Map() + for (const item of sorted) { - const offset = Math.floor((rangeEndDate.getTime() - parseIsoDate(item.day).getTime()) / DAY_MS) + const itemDate = parseIsoDate(item.day) + const offset = Math.floor((rangeEndDate.getTime() - itemDate.getTime()) / DAY_MS) if (offset < 0) continue const idx = Math.floor(offset / 7) buckets.set(idx, (buckets.get(idx) ?? 0) + item.value) diff --git a/test/unit/app/utils/chart-data-buckets.spec.ts b/test/unit/app/utils/chart-data-buckets.spec.ts index 8538f18138..141a9688c3 100644 --- a/test/unit/app/utils/chart-data-buckets.spec.ts +++ b/test/unit/app/utils/chart-data-buckets.spec.ts @@ -84,7 +84,7 @@ describe('buildWeeklyEvolution', () => { expect(result[1]!.weekEnd).toBe('2025-03-10') }) - it('aligns from last non-zero data day, ignoring trailing zeros', () => { + it('always aligns from rangeEnd, even with trailing zeros', () => { const daily = [ { day: '2025-03-01', value: 10 }, { day: '2025-03-02', value: 10 }, @@ -99,10 +99,14 @@ describe('buildWeeklyEvolution', () => { const result = buildWeeklyEvolution(daily, '2025-03-01', '2025-03-09') - expect(result).toHaveLength(1) - expect(result[0]!.value).toBe(70) + // Bucket 0: 03-03..03-09 = 50, Bucket 1: 03-01..03-02 (partial, scaled) + expect(result).toHaveLength(2) expect(result[0]!.weekStart).toBe('2025-03-01') - expect(result[0]!.weekEnd).toBe('2025-03-07') + expect(result[0]!.weekEnd).toBe('2025-03-02') + expect(result[0]!.value).toBe(Math.round((20 * 7) / 2)) + expect(result[1]!.weekStart).toBe('2025-03-03') + expect(result[1]!.weekEnd).toBe('2025-03-09') + expect(result[1]!.value).toBe(50) }) it('returns empty array for empty input', () => { From a201a36758039233529493788b8043f779f16971 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Sun, 15 Mar 2026 06:16:41 +0100 Subject: [PATCH 7/7] fix: make line-height a constant --- app/components/Code/Viewer.vue | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/components/Code/Viewer.vue b/app/components/Code/Viewer.vue index 5e924f27e6..2b1338db12 100644 --- a/app/components/Code/Viewer.vue +++ b/app/components/Code/Viewer.vue @@ -13,13 +13,14 @@ const codeRef = useTemplateRef('codeRef') // Using this so we can track the height of each line, and therefore compute digit sidebar const lineMultipliers = ref([]) +const LINE_HEIGHT_PX = 24 // also used in css function updateLineMultipliers() { if (!codeRef.value) return const lines = Array.from(codeRef.value.querySelectorAll('code > .line')) - lineMultipliers.value = lines - .map(line => Math.round(parseFloat(getComputedStyle(line).height) / 24)) // since each line "row" is 24px high - .filter(m => m > 0) + lineMultipliers.value = lines.map(line => + Math.max(1, Math.round(parseFloat(getComputedStyle(line).height) / LINE_HEIGHT_PX)), + ) } watch( @@ -179,8 +180,8 @@ watch( display: flex; flex-wrap: wrap; /* Ensure consistent height matching line numbers */ - line-height: 24px; - min-height: 24px; + line-height: calc(v-bind(LINE_HEIGHT_PX) * 1px); + min-height: calc(v-bind(LINE_HEIGHT_PX) * 1px); white-space: pre-wrap; overflow: hidden; transition: background-color 0.1s;