1+
2+ < head >
3+ < meta charset ="UTF-8 ">
4+ < title > Diff</ title >
5+ < style >
6+ .no-changes-footer {
7+ padding : 12px ;
8+ margin : 8px ;
9+ background : # e8f5e9 ;
10+ color : # 2e7d32 ;
11+ border : 1px solid # c8e6c9 ;
12+ border-radius : 4px ;
13+ font-family : sans-serif;
14+ font-size : 14px ;
15+ text-align : center;
16+ }
17+
18+ .diff-line {
19+ display : flex;
20+ font-family : monospace;
21+ white-space : pre;
22+ margin : 0 ;
23+ padding : 0 ;
24+ line-height : 1.5 ;
25+ font-size : 13px ;
26+ align-items : center;
27+ }
28+
29+ .line-number {
30+ width : 80px ;
31+ flex-shrink : 0 ;
32+ color : # 666 ;
33+ padding : 0 10px ;
34+ text-align : right;
35+ background : # f5f5f5 ;
36+ height : 100% ;
37+ box-sizing : border-box;
38+ }
39+
40+ .original-line {
41+ border-right : 1px solid # eee ;
42+ }
43+
44+ .content {
45+ padding : 0 8px ;
46+ flex-grow : 1 ;
47+ white-space : pre-wrap;
48+ }
49+
50+ .ADDED {
51+ background-color : # ccffcc ;
52+ }
53+
54+ .REMOVED {
55+ background-color : # ffcccc ;
56+ }
57+
58+ .UNCHANGED {
59+ background-color : # f8f8f8 ;
60+ }
61+
62+ .hidden {
63+ display : none !important ;
64+ }
65+
66+ body {
67+ margin : 0 ;
68+ padding : 0 ;
69+ }
70+
71+ .controls label {
72+ margin-right : 12px ;
73+ cursor : pointer;
74+ user-select : none;
75+ }
76+
77+ .controls {
78+ display : flex;
79+ gap : 15px ;
80+ align-items : center;
81+ margin-bottom : 8px ;
82+ padding : 8px ;
83+ background : # f8f8f8 ;
84+ border-bottom : 1px solid # ddd ;
85+ font-family : sans-serif;
86+ font-size : 13px ;
87+ }
88+
89+ .controls button {
90+ padding : 4px 8px ;
91+ background : # e0e0e0 ;
92+ border : 1px solid # ccc ;
93+ border-radius : 3px ;
94+ cursor : pointer;
95+ font-size : 13px ;
96+ }
97+
98+ .controls button : hover {
99+ background : # d0d0d0 ;
100+ }
101+
102+ .copy-feedback {
103+ color : # 008000 ;
104+ font-size : 12px ;
105+ margin-left : 8px ;
106+ display : none;
107+ }
108+ </ style >
109+ </ head >
110+
111+ < body >
112+ < div class ="controls ">
113+ < div class ="toggle-group ">
114+ < label >
115+ < input type ="checkbox " checked onclick ="toggleVisibility('ADDED') "> Added
116+ </ label >
117+ < label >
118+ < input type ="checkbox " checked onclick ="toggleVisibility('REMOVED') "> Removed
119+ </ label >
120+ < label >
121+ < input type ="checkbox " checked onclick ="toggleVisibility('UNCHANGED') "> Context
122+ </ label >
123+ < label >
124+ < input type ="checkbox " checked onclick ="toggleLineNumbers() "> Numbers
125+ </ label >
126+ </ div >
127+ < div class ="copy-group ">
128+ < button onclick ="copyText() "> Copy</ button >
129+ < span class ="copy-feedback " id ="copyFeedback "> </ span >
130+ </ div >
131+ </ div >
132+
133+
134+
135+ < div class ="diff-container ">
136+ < div class ="diff-line UNCHANGED ">
137+ < div class ="line-number original-line "> 1</ div >
138+ < div class ="line-number revised-line "> 1</ div >
139+ < div class ="content "> {</ div >
140+ </ div >
141+ < div class ="diff-line UNCHANGED ">
142+ < div class ="line-number original-line "> 2</ div >
143+ < div class ="line-number revised-line "> 2</ div >
144+ < div class ="content "> "id": 123,</ div >
145+ </ div >
146+ < div class ="diff-line UNCHANGED ">
147+ < div class ="line-number original-line "> 3</ div >
148+ < div class ="line-number revised-line "> 3</ div >
149+ < div class ="content "> "name": "John Doe",</ div >
150+ </ div >
151+ < div class ="diff-line UNCHANGED ">
152+ < div class ="line-number original-line "> 4</ div >
153+ < div class ="line-number revised-line "> 4</ div >
154+ < div class ="content "> "email": "john.doe@example.com",</ div >
155+ </ div >
156+ < div class ="diff-line UNCHANGED ">
157+ < div class ="line-number original-line "> 5</ div >
158+ < div class ="line-number revised-line "> 5</ div >
159+ < div class ="content "> "isActive": true,</ div >
160+ </ div >
161+ < div class ="diff-line UNCHANGED ">
162+ < div class ="line-number original-line "> 6</ div >
163+ < div class ="line-number revised-line "> 6</ div >
164+ < div class ="content "> "roles": [</ div >
165+ </ div >
166+ < div class ="diff-line UNCHANGED ">
167+ < div class ="line-number original-line "> 7</ div >
168+ < div class ="line-number revised-line "> 7</ div >
169+ < div class ="content "> "admin",</ div >
170+ </ div >
171+ < div class ="diff-line UNCHANGED ">
172+ < div class ="line-number original-line "> 8</ div >
173+ < div class ="line-number revised-line "> 8</ div >
174+ < div class ="content "> "user"</ div >
175+ </ div >
176+ < div class ="diff-line UNCHANGED ">
177+ < div class ="line-number original-line "> 9</ div >
178+ < div class ="line-number revised-line "> 9</ div >
179+ < div class ="content "> ],</ div >
180+ </ div >
181+ < div class ="diff-line UNCHANGED ">
182+ < div class ="line-number original-line "> 10</ div >
183+ < div class ="line-number revised-line "> 10</ div >
184+ < div class ="content "> "address": {</ div >
185+ </ div >
186+ < div class ="diff-line REMOVED ">
187+ < div class ="line-number original-line "> 11</ div >
188+ < div class ="line-number revised-line "> -</ div >
189+ < div class ="content "> "street": "123 Main St",</ div >
190+ </ div >
191+ < div class ="diff-line REMOVED ">
192+ < div class ="line-number original-line "> 13</ div >
193+ < div class ="line-number revised-line "> -</ div >
194+ < div class ="content "> "zipcode": "10001"</ div >
195+ </ div >
196+ < div class ="diff-line ADDED ">
197+ < div class ="line-number original-line "> -</ div >
198+ < div class ="line-number revised-line "> 11</ div >
199+ < div class ="content "> "city": "New York",</ div >
200+ </ div >
201+ < div class ="diff-line REMOVED ">
202+ < div class ="line-number original-line "> 14</ div >
203+ < div class ="line-number revised-line "> -</ div >
204+ < div class ="content "> }</ div >
205+ </ div >
206+ < div class ="diff-line ADDED ">
207+ < div class ="line-number original-line "> -</ div >
208+ < div class ="line-number revised-line "> 12</ div >
209+ < div class ="content "> "zipcode": "10001",</ div >
210+ </ div >
211+ < div class ="diff-line REMOVED ">
212+ < div class ="line-number original-line "> 15</ div >
213+ < div class ="line-number revised-line "> -</ div >
214+ < div class ="content "> }</ div >
215+ </ div >
216+ < div class ="diff-line ADDED ">
217+ < div class ="line-number original-line "> -</ div >
218+ < div class ="line-number revised-line "> 13</ div >
219+ < div class ="content "> "additional": "test"</ div >
220+ </ div >
221+ < div class ="diff-line ADDED ">
222+ < div class ="line-number original-line "> -</ div >
223+ < div class ="line-number revised-line "> 14</ div >
224+ < div class ="content "> }</ div >
225+ </ div >
226+ < div class ="diff-line ADDED ">
227+ < div class ="line-number original-line "> -</ div >
228+ < div class ="line-number revised-line "> 15</ div >
229+ < div class ="content "> }</ div >
230+ </ div >
231+ </ div >
232+
233+ < script >
234+ function showFeedback ( message ) {
235+ const feedback = document . getElementById ( 'copyFeedback' ) ;
236+ feedback . textContent = message ;
237+ feedback . style . display = 'inline' ;
238+ setTimeout ( ( ) => feedback . style . display = 'none' , 2000 ) ;
239+ }
240+
241+ function copyText ( ) {
242+ const visibleContents = document . querySelectorAll ( '.diff-line:not(.hidden) .content' ) ;
243+ const lines = Array . from ( visibleContents ) . map ( content => content . innerText ) ;
244+
245+ navigator . clipboard . writeText ( lines . join ( '\n' ) )
246+ . then ( ( ) => showFeedback ( 'Text copied!' ) )
247+ . catch ( err => console . error ( 'Copy failed' , err ) ) ;
248+ }
249+
250+ function toggleVisibility ( className ) {
251+ document . querySelectorAll ( `.${ className } ` ) . forEach ( element => {
252+ element . classList . toggle ( 'hidden' ) ;
253+ } ) ;
254+ }
255+
256+ function toggleLineNumbers ( ) {
257+ document . querySelectorAll ( '.line-number' ) . forEach ( element => {
258+ element . classList . toggle ( 'hidden' ) ;
259+ } ) ;
260+ }
261+ </ script >
262+ </ body >
0 commit comments