Skip to content

Commit b40edb9

Browse files
Merge pull request #39 from technikhil314/develop
Develop
2 parents 0a1d877 + 8c97fa2 commit b40edb9

File tree

7 files changed

+434
-361
lines changed

7 files changed

+434
-361
lines changed

components/diffActionBar.vue

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
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-[70px]
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 hover:scale-105 hover:shadow-lg"
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 hover:scale-105 hover:shadow-lg"
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 hover:scale-105 hover:shadow-lg copy-uri-button"
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+
import { putToClipboard } from '~/helpers/utils'
146+
export default {
147+
data() {
148+
return {
149+
copied: this.copied,
150+
}
151+
},
152+
beforeCreate() {
153+
this.copied = false
154+
},
155+
mounted() {
156+
const lhsDiffNode = document.getElementById('lhsDiff')
157+
const rhsDiffNode = document.getElementById('rhsDiff')
158+
if (lhsDiffNode && rhsDiffNode) {
159+
const isLHSBigger =
160+
lhsDiffNode.children.length > rhsDiffNode.children.length
161+
let comparator, comparer
162+
if (isLHSBigger) {
163+
comparer = lhsDiffNode
164+
comparator = rhsDiffNode
165+
} else {
166+
comparer = rhsDiffNode
167+
comparator = lhsDiffNode
168+
}
169+
this.comparator = comparator
170+
this.treeWalker = document.createTreeWalker(
171+
comparer,
172+
NodeFilter.SHOW_ELEMENT,
173+
{
174+
acceptNode: (node) => {
175+
return (
176+
node.classList.contains('bg-red-200') ||
177+
node.classList.contains('bg-green-200')
178+
)
179+
},
180+
}
181+
)
182+
}
183+
},
184+
methods: {
185+
copyUrlToClipboard() {
186+
putToClipboard(
187+
window.location.href,
188+
'Link copied to your clipboard',
189+
this.$store
190+
)
191+
this.copied = true
192+
setTimeout(() => {
193+
this.copied = false
194+
}, 5000)
195+
},
196+
toggleInSyncScroll() {
197+
this.$store.commit('scrollInSync/toggle')
198+
},
199+
goToNextDiff() {
200+
const currentNode = this.treeWalker.currentNode
201+
const nextNode = this.treeWalker.nextNode()
202+
if (nextNode) {
203+
const currentNodeIndex = Array.prototype.indexOf.call(
204+
currentNode.parentElement.children,
205+
currentNode
206+
)
207+
const nextNodeIndex = Array.prototype.indexOf.call(
208+
nextNode.parentElement.children,
209+
nextNode
210+
)
211+
const comparatorCurrentNode = this.comparator.children[currentNodeIndex]
212+
const comparatorNextNode = this.comparator.children[nextNodeIndex]
213+
currentNode.querySelector('p').classList.remove('selected')
214+
comparatorCurrentNode.querySelector('p').classList.remove('selected')
215+
nextNode.querySelector('p').classList.add('selected')
216+
comparatorNextNode.querySelector('p').classList.add('selected')
217+
nextNode.scrollIntoView()
218+
comparatorNextNode.scrollIntoView()
219+
}
220+
},
221+
goToPreviousDiff() {
222+
const currentNode = this.treeWalker.currentNode
223+
const prevNode = this.treeWalker.previousNode()
224+
if (prevNode) {
225+
const currentNodeIndex = Array.prototype.indexOf.call(
226+
currentNode.parentElement.children,
227+
currentNode
228+
)
229+
const prevNodeIndex = Array.prototype.indexOf.call(
230+
prevNode.parentElement.children,
231+
prevNode
232+
)
233+
const comparatorCurrentNode = this.comparator.children[currentNodeIndex]
234+
const comparatorPrevNode = this.comparator.children[prevNodeIndex]
235+
currentNode.querySelector('p').classList.remove('selected')
236+
comparatorCurrentNode.querySelector('p').classList.remove('selected')
237+
prevNode.querySelector('p').classList.add('selected')
238+
comparatorPrevNode.querySelector('p').classList.add('selected')
239+
prevNode.scrollIntoView()
240+
comparatorPrevNode.scrollIntoView()
241+
}
242+
},
243+
},
244+
}
245+
</script>
246+
<style lang="scss">
247+
.copy-uri-button:hover svg {
248+
@apply rotate-12;
249+
}
250+
</style>

components/navbar.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
class="sticky top-0 left-0 right-0 z-10 text-gray-800 shadow-lg dark:shadow-dark bg-gray-50 dark:bg-gray-900 dark:text-gray-50"
44
>
55
<div class="container flex items-center py-4 m-auto">
6-
<div v-if="showBackButton" class="hidden mr-4 md:block">
6+
<div
7+
v-if="showBackButton"
8+
class="hidden mr-4 md:block hover:scale-110 filter hover:drop-shadow-md"
9+
>
710
<NuxtLink to="/">
811
<svg
912
class="w-6 h-6"
@@ -62,7 +65,7 @@
6265
<slot name="right" />
6366
<button
6467
type="button"
65-
class="inline-flex items-center justify-center ml-4 bg-transparent border-2 border-gray-700 rounded-full shadow-lg w-9 h-9 active:scale-y-75"
68+
class="inline-flex items-center justify-center ml-4 bg-transparent border-2 border-gray-700 rounded-full shadow-lg w-9 h-9 active:scale-y-75 hover:scale-105 hover:shadow-lg"
6669
aria-label="Toggle Dark Mode"
6770
@click="toggleDarkMode"
6871
>
@@ -104,7 +107,6 @@
104107
<ul class="flex items-center justify-end">
105108
<li class="relative inline-block ml-2 lg:ml-4">
106109
<a
107-
class=""
108110
href="https://github.com/technikhil314/offline-diff-viewer"
109111
title="go to github repository of this open source project"
110112
>

components/singleDiff.vue

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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+
import { putToClipboard } from '~/helpers/utils'
33+
export default {
34+
props: {
35+
diff: {
36+
type: Array,
37+
required: true,
38+
},
39+
label: {
40+
type: String,
41+
required: true,
42+
},
43+
modifiedClassString: {
44+
type: String,
45+
required: true,
46+
},
47+
id: {
48+
type: String,
49+
required: true,
50+
},
51+
},
52+
computed: {
53+
isSrollInSyncEnabled() {
54+
return this.$store.state.scrollInSync.isEnabled
55+
},
56+
},
57+
methods: {
58+
copyTextToClipboard(e) {
59+
putToClipboard(
60+
e.currentTarget.parentNode.parentNode.innerText
61+
.split('\n\n')
62+
.join('\n'),
63+
'Text copied to your clipboard',
64+
this.$store
65+
)
66+
},
67+
},
68+
}
69+
</script>
70+
71+
<style lang="scss" scoped>
72+
/* line numbers in diff view */
73+
.line-number-gutter {
74+
counter-reset: line-numbers;
75+
76+
--line-number-gutter-width: calc(var(--max-line-number-characher) + 10px);
77+
&::before {
78+
content: '';
79+
width: var(--line-number-gutter-width);
80+
@apply bg-gray-300 dark:bg-gray-700 inline-block left-0 top-0 bottom-0 absolute text-sm;
81+
}
82+
@apply relative;
83+
p {
84+
padding-left: calc(var(--line-number-gutter-width) - 10px);
85+
line-height: 1.65;
86+
@apply relative;
87+
&.selected {
88+
@apply dark:bg-blue-800 bg-blue-200;
89+
}
90+
&:hover {
91+
@apply bg-gray-200 dark:bg-gray-600;
92+
& > span {
93+
@apply dark:mix-blend-hard-light dark:bg-blend-multiply;
94+
}
95+
}
96+
&::before {
97+
counter-increment: line-numbers;
98+
content: counter(line-numbers);
99+
width: var(--line-number-gutter-width);
100+
@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;
101+
}
102+
}
103+
}
104+
</style>

0 commit comments

Comments
 (0)