Skip to content

Commit 30111f3

Browse files
committed
feat: add word wrap toggle to code viewer (#2027)
1 parent 7f2fc1a commit 30111f3

File tree

3 files changed

+54
-7
lines changed

3 files changed

+54
-7
lines changed

app/components/Code/Viewer.vue

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const props = defineProps<{
33
html: string
44
lines: number
55
selectedLines: { start: number; end: number } | null
6+
wordWrap?: boolean
67
}>()
78
89
const emit = defineEmits<{
@@ -113,9 +114,9 @@ watch(
113114
</div>
114115

115116
<!-- Code content -->
116-
<div class="code-content flex-1 overflow-x-auto min-w-0">
117+
<div class="code-content flex-1 min-w-0" :class="wordWrap ? 'overflow-x-hidden' : 'overflow-x-auto'">
117118
<!-- eslint-disable vue/no-v-html -- HTML is generated server-side by Shiki -->
118-
<div ref="codeRef" class="code-lines min-w-full w-fit" v-html="html" />
119+
<div ref="codeRef" class="code-lines min-w-full w-fit" :class="{ 'word-wrap': wordWrap }" v-html="html" />
119120
<!-- eslint-enable vue/no-v-html -->
120121
</div>
121122
</div>
@@ -155,6 +156,21 @@ watch(
155156
transition: background-color 0.1s;
156157
}
157158
159+
.code-content.word-wrap-active :deep(.line),
160+
.code-content:has(.word-wrap) :deep(.line) {
161+
white-space: pre-wrap;
162+
overflow-wrap: break-word;
163+
max-height: none;
164+
overflow: visible;
165+
}
166+
167+
.code-lines.word-wrap :deep(.line) {
168+
white-space: pre-wrap;
169+
overflow-wrap: break-word;
170+
max-height: none;
171+
overflow: visible;
172+
}
173+
158174
/* Highlighted lines in code content - extend full width with negative margin */
159175
.code-content :deep(.line.highlighted) {
160176
@apply bg-yellow-500/20;

app/pages/package-code/[[org]]/[packageName]/v/[version]/[...filePath].vue

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ const markdownViewModes = [
267267
268268
const markdownViewMode = shallowRef<(typeof markdownViewModes)[number]['key']>('preview')
269269
270+
const wordWrap = shallowRef(false)
271+
270272
const bytesFormatter = useBytesFormatter()
271273
272274
// Keep latestVersion for comparison (to show "(latest)" badge)
@@ -416,6 +418,17 @@ defineOgImageComponent('Default', {
416418
</nav>
417419
</div>
418420
<div class="flex items-center gap-2" v-if="isViewingFile && !isBinaryFile && fileContent">
421+
<button
422+
type="button"
423+
class="px-2 py-1 font-mono text-xs border rounded transition-colors inline-flex items-center gap-1"
424+
:class="wordWrap ? 'bg-accent/10 text-accent border-accent/30' : 'text-fg-muted bg-bg-subtle border-border hover:text-fg hover:border-border-hover'"
425+
:aria-pressed="wordWrap"
426+
:title="$t('code.toggle_word_wrap')"
427+
@click="wordWrap = !wordWrap"
428+
>
429+
<span class="i-lucide:wrap-text w-3 h-3" aria-hidden="true" />
430+
{{ $t('code.toggle_word_wrap') }}
431+
</button>
419432
<button
420433
v-if="selectedLines"
421434
type="button"
@@ -462,6 +475,7 @@ defineOgImageComponent('Default', {
462475
:html="fileContent.html"
463476
:lines="fileContent.lines"
464477
:selected-lines="selectedLines"
478+
:word-wrap="wordWrap"
465479
@line-click="handleLineClick"
466480
/>
467481
<div class="sticky bottom-0 bg-bg border-t border-border px-4 py-1">

i18n/locales/en.json

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@
1919
"social": "social",
2020
"chat": "chat",
2121
"builders_chat": "builders",
22-
"keyboard_shortcuts": "keyboard shortcuts"
22+
"keyboard_shortcuts": "keyboard shortcuts",
23+
"product": "Product",
24+
"legal": "Legal",
25+
"community": "Community"
2326
},
2427
"shortcuts": {
2528
"section": {
@@ -207,6 +210,8 @@
207210
"members": "members"
208211
},
209212
"scroll_to_top": "Scroll to top",
213+
"previous": "Previous",
214+
"next": "Next",
210215
"cancel": "Cancel",
211216
"save": "Save",
212217
"edit": "Edit",
@@ -318,7 +323,8 @@
318323
"docs": "docs",
319324
"fund": "fund",
320325
"compare": "compare",
321-
"compare_this_package": "compare this package"
326+
"compare_this_package": "compare this package",
327+
"dependents": "dependents"
322328
},
323329
"likes": {
324330
"like": "Like this package",
@@ -352,6 +358,13 @@
352358
"title": "Run",
353359
"locally": "Run locally"
354360
},
361+
"dependents": {
362+
"title": "Dependents",
363+
"subtitle": "Packages that depend on {name}",
364+
"count": "{count} dependent | {count} dependents",
365+
"none": "No packages found that depend on {name}",
366+
"error": "Failed to load dependents"
367+
},
355368
"readme": {
356369
"title": "Readme",
357370
"no_readme": "No README available.",
@@ -454,7 +467,8 @@
454467
"outdated_minor": "{count} minor version behind (latest: {latest}) | {count} minor versions behind (latest: {latest})",
455468
"outdated_patch": "Patch update available (latest: {latest})",
456469
"has_replacement": "This dependency has suggested replacements",
457-
"vulnerabilities_count": "{count} vulnerability | {count} vulnerabilities"
470+
"vulnerabilities_count": "{count} vulnerability | {count} vulnerabilities",
471+
"none": "No dependencies"
458472
},
459473
"peer_dependencies": {
460474
"title": "Peer Dependency ({count}) | Peer Dependencies ({count})",
@@ -564,7 +578,9 @@
564578
},
565579
"license": {
566580
"view_spdx": "View license text on SPDX",
567-
"none": "None"
581+
"none": "None",
582+
"changed_badge": "changed",
583+
"changed": "License changed from {latest} in the latest version"
568584
},
569585
"vulnerabilities": {
570586
"tree_found": "{vulns} vulnerability in {packages}/{total} packages | {vulns} vulnerabilities in {packages}/{total} packages",
@@ -840,7 +856,8 @@
840856
},
841857
"file_path": "File path",
842858
"binary_file": "Binary file",
843-
"binary_rendering_warning": "File type \"{contentType}\" is not supported for preview."
859+
"binary_rendering_warning": "File type \"{contentType}\" is not supported for preview.",
860+
"toggle_word_wrap": "Word wrap"
844861
},
845862
"badges": {
846863
"provenance": {

0 commit comments

Comments
 (0)