Skip to content

Commit 238b31d

Browse files
committed
refactor: broken diff.vuw in multiple small components
1 parent 0a1d877 commit 238b31d

File tree

5 files changed

+409
-323
lines changed

5 files changed

+409
-323
lines changed

components/diffActionBar.vue

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
<template>
2+
<section
3+
class="
4+
flex
5+
items-center
6+
justify-between
7+
px-4
8+
py-2
9+
mb-4
10+
sticky
11+
top-[80px]
12+
dark:bg-gray-700
13+
bg-gray-300
14+
dark:bg-opacity-50
15+
bg-opacity-50
16+
backdrop-blur-sm
17+
rounded-md
18+
shadow-lg
19+
border border-gray-500
20+
w-full
21+
z-10
22+
"
23+
>
24+
<div class="flex gap-4">
25+
<div
26+
id="toggleScrollInSyncSection"
27+
class="inline-flex items-center gap-1"
28+
>
29+
<label
30+
for="toggleScrollInSync"
31+
class="text-gray-800 select-none dark:text-gray-50"
32+
>
33+
Scroll in sync
34+
</label>
35+
<input
36+
id="toggleScrollInSync"
37+
type="checkbox"
38+
checked
39+
class="form-checkbox"
40+
@click="toggleInSyncScroll"
41+
/>
42+
</div>
43+
<div id="nextDiffSection" class="inline-flex items-center gap-1">
44+
<button
45+
id="nextDiff"
46+
class="inline-flex items-center justify-center px-1 py-1 text-sm text-gray-600 transition-transform transform bg-gray-300 border border-gray-800 rounded-sm outline-none dark:border-gray-400 dark:text-white dark:bg-gray-800 align-center focus:ring-4 active:scale-y-75"
47+
aria-label="Go to next diff"
48+
type="button"
49+
@click="goToNextDiff"
50+
>
51+
Next diff
52+
<svg
53+
class="w-4 h-4"
54+
fill="none"
55+
stroke="currentColor"
56+
viewBox="0 0 24 24"
57+
xmlns="http://www.w3.org/2000/svg"
58+
>
59+
<path
60+
stroke-linecap="round"
61+
stroke-linejoin="round"
62+
stroke-width="2"
63+
d="M16 17l-4 4m0 0l-4-4m4 4V3"
64+
></path>
65+
</svg>
66+
</button>
67+
</div>
68+
<div id="prevDiffSection" class="inline-flex items-center gap-1">
69+
<button
70+
id="prevDiff"
71+
class="inline-flex items-center justify-center px-1 py-1 text-sm text-gray-600 transition-transform transform bg-gray-300 border border-gray-800 rounded-sm outline-none dark:border-gray-400 dark:text-white dark:bg-gray-800 align-center focus:ring-4 active:scale-y-75"
72+
aria-label="Go to previous diff"
73+
type="button"
74+
@click="goToPreviousDiff"
75+
>
76+
Previous diff
77+
<svg
78+
class="w-4 h-4"
79+
fill="none"
80+
stroke="currentColor"
81+
viewBox="0 0 24 24"
82+
xmlns="http://www.w3.org/2000/svg"
83+
>
84+
<path
85+
stroke-linecap="round"
86+
stroke-linejoin="round"
87+
stroke-width="2"
88+
d="M8 7l4-4m0 0l4 4m-4-4v18"
89+
></path>
90+
</svg>
91+
</button>
92+
</div>
93+
</div>
94+
<div>
95+
<button
96+
type="button"
97+
class="inline-flex items-center justify-center gap-1 p-2 text-sm transition-transform transform rounded-md shadow outline-none justify-self-end focus:ring-4 active:scale-y-75"
98+
aria-label="Copy url to clipboard"
99+
:class="{
100+
'bg-blue-500 text-white': !copied,
101+
'bg-green-500 text-gray-800': copied,
102+
}"
103+
@click="copyUrlToClipboard"
104+
>
105+
<span v-show="copied" class="inline">
106+
<svg
107+
class="w-4 h-4"
108+
fill="none"
109+
stroke="currentColor"
110+
viewBox="0 0 24 24"
111+
xmlns="http://www.w3.org/2000/svg"
112+
>
113+
<path
114+
stroke-linecap="round"
115+
stroke-linejoin="round"
116+
stroke-width="2"
117+
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"
118+
></path>
119+
</svg>
120+
</span>
121+
<span v-show="copied" class="hidden md:inline-block">Copied</span>
122+
<span v-show="!copied" class="inline">
123+
<svg
124+
class="w-4 h-4"
125+
fill="none"
126+
stroke="currentColor"
127+
viewBox="0 0 24 24"
128+
xmlns="http://www.w3.org/2000/svg"
129+
>
130+
<path
131+
stroke-linecap="round"
132+
stroke-linejoin="round"
133+
stroke-width="2"
134+
d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"
135+
></path>
136+
</svg>
137+
</span>
138+
<span v-show="!copied" class="hidden md:inline-block">Copy link</span>
139+
</button>
140+
</div>
141+
</section>
142+
</template>
143+
144+
<script>
145+
export default {
146+
data() {
147+
return {
148+
copied: this.copied,
149+
}
150+
},
151+
beforeCreate() {
152+
this.copied = false
153+
},
154+
mounted() {
155+
const lhsDiffNode = document.getElementById('lhsDiff')
156+
const rhsDiffNode = document.getElementById('rhsDiff')
157+
if (lhsDiffNode && rhsDiffNode) {
158+
const isLHSBigger =
159+
lhsDiffNode.children.length > rhsDiffNode.children.length
160+
let comparator, comparer
161+
if (isLHSBigger) {
162+
comparer = lhsDiffNode
163+
comparator = rhsDiffNode
164+
} else {
165+
comparer = rhsDiffNode
166+
comparator = lhsDiffNode
167+
}
168+
this.comparator = comparator
169+
this.treeWalker = document.createTreeWalker(
170+
comparer,
171+
NodeFilter.SHOW_ELEMENT,
172+
{
173+
acceptNode: (node) => {
174+
return (
175+
node.classList.contains('bg-red-200') ||
176+
node.classList.contains('bg-green-200')
177+
)
178+
},
179+
}
180+
)
181+
}
182+
},
183+
methods: {
184+
putToClipboard(textToPut, toastContent) {
185+
navigator.clipboard.writeText(textToPut)
186+
this.$store.commit('toast/show', {
187+
show: true,
188+
content: toastContent,
189+
iconHTML: `
190+
<svg
191+
class="w-6 h-6"
192+
fill="none"
193+
stroke="currentColor"
194+
viewBox="0 0 24 24"
195+
xmlns="http://www.w3.org/2000/svg"
196+
>
197+
<path
198+
stroke-linecap="round"
199+
stroke-linejoin="round"
200+
stroke-width="2"
201+
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
202+
></path>
203+
</svg>
204+
`,
205+
theme: 'success',
206+
})
207+
},
208+
copyUrlToClipboard() {
209+
this.putToClipboard(window.location.href, 'Link copied to your clipboard')
210+
this.copied = true
211+
setTimeout(() => {
212+
this.copied = false
213+
}, 5000)
214+
},
215+
toggleInSyncScroll() {
216+
this.$store.commit('scrollInSync/toggle')
217+
},
218+
goToNextDiff() {
219+
const currentNode = this.treeWalker.currentNode
220+
const nextNode = this.treeWalker.nextNode()
221+
if (nextNode) {
222+
const currentNodeIndex = Array.prototype.indexOf.call(
223+
currentNode.parentElement.children,
224+
currentNode
225+
)
226+
const nextNodeIndex = Array.prototype.indexOf.call(
227+
nextNode.parentElement.children,
228+
nextNode
229+
)
230+
const comparatorCurrentNode = this.comparator.children[currentNodeIndex]
231+
const comparatorNextNode = this.comparator.children[nextNodeIndex]
232+
currentNode.querySelector('p').classList.remove('selected')
233+
comparatorCurrentNode.querySelector('p').classList.remove('selected')
234+
nextNode.querySelector('p').classList.add('selected')
235+
comparatorNextNode.querySelector('p').classList.add('selected')
236+
nextNode.scrollIntoView()
237+
comparatorNextNode.scrollIntoView()
238+
}
239+
},
240+
goToPreviousDiff() {
241+
const currentNode = this.treeWalker.currentNode
242+
const prevNode = this.treeWalker.previousNode()
243+
if (prevNode) {
244+
const currentNodeIndex = Array.prototype.indexOf.call(
245+
currentNode.parentElement.children,
246+
currentNode
247+
)
248+
const prevNodeIndex = Array.prototype.indexOf.call(
249+
prevNode.parentElement.children,
250+
prevNode
251+
)
252+
const comparatorCurrentNode = this.comparator.children[currentNodeIndex]
253+
const comparatorPrevNode = this.comparator.children[prevNodeIndex]
254+
currentNode.querySelector('p').classList.remove('selected')
255+
comparatorCurrentNode.querySelector('p').classList.remove('selected')
256+
prevNode.querySelector('p').classList.add('selected')
257+
comparatorPrevNode.querySelector('p').classList.add('selected')
258+
prevNode.scrollIntoView()
259+
comparatorPrevNode.scrollIntoView()
260+
}
261+
},
262+
},
263+
}
264+
</script>

components/singleDiff.vue

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<template>
2+
<div class="flex flex-col w-1/2 gap-2">
3+
<p class="flex-grow-0 text-lg font-bold text-center capitalize">
4+
{{ label }}
5+
</p>
6+
<div
7+
:id="id"
8+
class="relative flex-1 px-4 py-2 border-2 rounded-md dark:border-gray-500 line-number-gutter min-h-80"
9+
:class="{
10+
'overflow-y-auto max-h-screen--nav': !isSrollInSyncEnabled,
11+
}"
12+
>
13+
<RTStickyCopyButton
14+
:aria-label="'Copy the content to clipboard'"
15+
:click-handler="copyTextToClipboard"
16+
/>
17+
<div
18+
v-for="(lineDiff, index) in diff"
19+
:key="index"
20+
:class="{
21+
[`${modifiedClassString} rounded-sm`]:
22+
lineDiff.includes('isModified'),
23+
}"
24+
>
25+
<p class="break-all whitespace-pre-wrap" v-html="lineDiff"></p>
26+
</div>
27+
</div>
28+
</div>
29+
</template>
30+
31+
<script>
32+
export default {
33+
props: {
34+
diff: {
35+
type: Array,
36+
required: true,
37+
},
38+
label: {
39+
type: String,
40+
required: true,
41+
},
42+
modifiedClassString: {
43+
type: String,
44+
required: true,
45+
},
46+
id: {
47+
type: String,
48+
required: true,
49+
},
50+
},
51+
computed: {
52+
isSrollInSyncEnabled() {
53+
return this.$store.state.scrollInSync.isEnabled
54+
},
55+
},
56+
methods: {
57+
copyTextToClipboard(e) {
58+
this.putToClipboard(
59+
e.currentTarget.parentNode.parentNode.innerText
60+
.split('\n\n')
61+
.join('\n'),
62+
'Text copied to your clipboard'
63+
)
64+
},
65+
},
66+
}
67+
</script>
68+
69+
<style lang="scss" scoped>
70+
/* line numbers in diff view */
71+
.line-number-gutter {
72+
counter-reset: line-numbers;
73+
74+
--line-number-gutter-width: calc(var(--max-line-number-characher) + 10px);
75+
&::before {
76+
content: '';
77+
width: var(--line-number-gutter-width);
78+
@apply bg-gray-300 dark:bg-gray-700 inline-block left-0 top-0 bottom-0 absolute text-sm;
79+
}
80+
@apply relative;
81+
p {
82+
padding-left: calc(var(--line-number-gutter-width) - 10px);
83+
line-height: 1.65;
84+
@apply relative;
85+
&.selected {
86+
@apply dark:bg-blue-800 bg-blue-200;
87+
}
88+
&:hover {
89+
@apply bg-gray-200 dark:bg-gray-600;
90+
& > span {
91+
@apply dark:mix-blend-hard-light dark:bg-blend-multiply;
92+
}
93+
}
94+
&::before {
95+
counter-increment: line-numbers;
96+
content: counter(line-numbers);
97+
width: var(--line-number-gutter-width);
98+
@apply absolute left-0 top-0 -mx-4 bg-gray-200 dark:bg-gray-700 dark:text-gray-50 text-gray-500 inline-flex justify-center items-center text-sm h-full;
99+
}
100+
}
101+
}
102+
</style>

0 commit comments

Comments
 (0)