Skip to content

Commit d168a29

Browse files
Add files via upload
1 parent 07339e9 commit d168a29

File tree

3 files changed

+355
-0
lines changed

3 files changed

+355
-0
lines changed

index.html

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<!DOCTYPE html>
2+
<html lang="ru">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Сравнение текста и кода</title>
7+
<link rel="preconnect" href="https://fonts.googleapis.com">
8+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9+
<link href="https://fonts.googleapis.com/css2?family=Source+Code+Pro:ital,wght@0,200..900;1,200..900&display=swap" rel="stylesheet">
10+
<link href="style.css" rel="stylesheet" type="text/css" />
11+
</head>
12+
<body>
13+
<div class="container">
14+
<h1>Сравнение текста и кода</h1>
15+
<div class="input-container">
16+
<div class="input-wrapper">
17+
<textarea id="input1" placeholder="Введите первый текст или код здесь"></textarea>
18+
</div>
19+
<div class="input-wrapper">
20+
<textarea id="input2" placeholder="Введите второй текст или код здесь"></textarea>
21+
</div>
22+
</div>
23+
<div class="controls">
24+
<select id="diffType">
25+
<option value="chars">Посимвольное сравнение</option>
26+
<option value="words">Пословное сравнение</option>
27+
<option value="lines">Построчное сравнение</option>
28+
</select>
29+
<button id="compareBtn">Сравнить</button>
30+
</div>
31+
<div class="output-container">
32+
<div id="output1" class="output"></div>
33+
<div id="output2" class="output"></div>
34+
</div>
35+
<div id="diffSummary" class="diff-summary"></div>
36+
</div>
37+
<script src="https://cdnjs.cloudflare.com/ajax/libs/diff_match_patch/20121119/diff_match_patch.js"></script>
38+
<script src="script.js"></script>
39+
</body>
40+
</html>

script.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
window.onload = function() {
2+
if (typeof diff_match_patch === 'undefined') {
3+
console.error('Библиотека diff_match_patch не была загружена.');
4+
return;
5+
}
6+
7+
const dmp = new diff_match_patch();
8+
9+
function compareTexts(text1, text2, diffType) {
10+
let diffs;
11+
switch (diffType) {
12+
case 'chars':
13+
diffs = dmp.diff_main(text1, text2);
14+
dmp.diff_cleanupSemantic(diffs);
15+
break;
16+
case 'words':
17+
diffs = dmp.diff_main(text1, text2);
18+
dmp.diff_cleanupSemantic(diffs);
19+
diffs = diffs.map(([op, text]) => [op, text.split(/\s+/)]);
20+
break;
21+
case 'lines':
22+
diffs = dmp.diff_main(text1, text2);
23+
dmp.diff_cleanupSemantic(diffs);
24+
diffs = diffs.map(([op, text]) => [op, text.split('\n')]);
25+
break;
26+
}
27+
28+
const result1 = [];
29+
const result2 = [];
30+
let diffCount = 0;
31+
32+
diffs.forEach(([op, data]) => {
33+
if (Array.isArray(data)) {
34+
data.forEach(item => {
35+
if (op === -1) {
36+
result1.push(`<span class="diff-remove">${escapeHtml(item)}<span class="diff-marker diff-marker-remove">-</span></span>`);
37+
diffCount++;
38+
} else if (op === 1) {
39+
result2.push(`<span class="diff-add">${escapeHtml(item)}<span class="diff-marker diff-marker-add">+</span></span>`);
40+
diffCount++;
41+
} else {
42+
result1.push(escapeHtml(item));
43+
result2.push(escapeHtml(item));
44+
}
45+
});
46+
} else {
47+
if (op === -1) {
48+
result1.push(`<span class="diff-remove">${escapeHtml(data)}<span class="diff-marker diff-marker-remove">-</span></span>`);
49+
diffCount++;
50+
} else if (op === 1) {
51+
result2.push(`<span class="diff-add">${escapeHtml(data)}<span class="diff-marker diff-marker-add">+</span></span>`);
52+
diffCount++;
53+
} else {
54+
result1.push(escapeHtml(data));
55+
result2.push(escapeHtml(data));
56+
}
57+
}
58+
});
59+
60+
return [result1.join(diffType === 'lines' ? '\n' : ' '), result2.join(diffType === 'lines' ? '\n' : ' '), diffCount];
61+
}
62+
63+
function escapeHtml(unsafe) {
64+
return unsafe
65+
.replace(/&/g, "&amp;")
66+
.replace(/</g, "&lt;")
67+
.replace(/>/g, "&gt;")
68+
.replace(/"/g, "&quot;")
69+
.replace(/'/g, "&#039;");
70+
}
71+
72+
document.getElementById('compareBtn').addEventListener('click', () => {
73+
const input1 = document.getElementById('input1').value;
74+
const input2 = document.getElementById('input2').value;
75+
const diffType = document.getElementById('diffType').value;
76+
const [result1, result2, diffCount] = compareTexts(input1, input2, diffType);
77+
78+
const output1 = document.getElementById('output1');
79+
const output2 = document.getElementById('output2');
80+
const diffSummary = document.getElementById('diffSummary');
81+
82+
output1.innerHTML = result1;
83+
output2.innerHTML = result2;
84+
diffSummary.textContent = `Всего различий: ${diffCount}`;
85+
86+
output1.classList.remove('fade-in');
87+
output2.classList.remove('fade-in');
88+
diffSummary.classList.remove('fade-in');
89+
90+
void output1.offsetWidth;
91+
void output2.offsetWidth;
92+
void diffSummary.offsetWidth;
93+
94+
output1.classList.add('fade-in');
95+
output2.classList.add('fade-in');
96+
diffSummary.classList.add('fade-in');
97+
});
98+
};

style.css

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
:root {
2+
--bg-color: #1e1e1e;
3+
--text-color: #e0e0e0;
4+
--primary-color: #2d2d2d;
5+
--secondary-color: #3a3a3a;
6+
--accent-color: #3cabff;
7+
--button-color: #006fc3;
8+
--diff-add: #355e3b;
9+
--diff-remove: #5e3535;
10+
--scrollbar-bg: #2d2d2d;
11+
--scrollbar-thumb: #4a4a4a;
12+
}
13+
14+
* {
15+
box-sizing: border-box;
16+
margin: 0;
17+
padding: 0;
18+
}
19+
20+
body {
21+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
22+
background-color: var(--bg-color);
23+
color: var(--text-color);
24+
line-height: 1.6;
25+
padding: 20px;
26+
min-height: 100vh;
27+
display: flex;
28+
flex-direction: column;
29+
}
30+
31+
.container {
32+
max-width: 1200px;
33+
width: -webkit-fill-available;
34+
margin: 0 auto;
35+
display: flex;
36+
flex-direction: column;
37+
flex-grow: 1;
38+
}
39+
40+
h1 {
41+
text-align: center;
42+
margin-bottom: 20px;
43+
font-family: 'Source Code Pro', 'Consolas', 'Courier New', monospace;
44+
letter-spacing: -1px;
45+
line-height: normal;
46+
opacity: 0.9;
47+
color: var(--accent-color);
48+
}
49+
50+
.input-container {
51+
display: flex;
52+
gap: 20px;
53+
margin-bottom: 20px;
54+
}
55+
56+
.input-wrapper {
57+
flex: 1;
58+
display: flex;
59+
flex-direction: column;
60+
}
61+
62+
textarea {
63+
width: 100%;
64+
height: 200px;
65+
background-color: var(--primary-color);
66+
color: var(--text-color);
67+
border: 1px solid var(--secondary-color);
68+
border-radius: 5px;
69+
padding: 10px;
70+
resize: vertical;
71+
transition: all 0.3s ease;
72+
font-family: 'Consolas', 'Courier New', monospace;
73+
font-size: 14px;
74+
}
75+
76+
textarea:focus {
77+
outline: none;
78+
border-color: var(--accent-color);
79+
box-shadow: 0 0 0 2px rgba(0, 120, 212, 0.2);
80+
}
81+
82+
textarea::-webkit-scrollbar,
83+
.output::-webkit-scrollbar,
84+
body::-webkit-scrollbar {
85+
width: 12px;
86+
}
87+
88+
textarea::-webkit-scrollbar-track,
89+
.output::-webkit-scrollbar-track,
90+
body::-webkit-scrollbar-track {
91+
background: var(--scrollbar-bg);
92+
}
93+
94+
textarea::-webkit-scrollbar-thumb,
95+
.output::-webkit-scrollbar-thumb,
96+
body::-webkit-scrollbar-thumb {
97+
background-color: var(--scrollbar-thumb);
98+
border-radius: 6px;
99+
border: 3px solid var(--scrollbar-bg);
100+
}
101+
102+
.controls {
103+
display: flex;
104+
justify-content: space-between;
105+
align-items: center;
106+
margin-bottom: 20px;
107+
}
108+
109+
button {
110+
background-color: var(--button-color);
111+
color: var(--text-color);
112+
border: none;
113+
border-radius: 5px;
114+
padding: 10px 20px;
115+
cursor: pointer;
116+
transition: all 0.3s ease;
117+
font-size: 16px;
118+
}
119+
120+
button:hover {
121+
background-color: #005a9e;
122+
}
123+
124+
select {
125+
background-color: var(--primary-color);
126+
color: var(--text-color);
127+
border: 1px solid var(--secondary-color);
128+
border-radius: 5px;
129+
padding: 8px;
130+
font-size: 14px;
131+
}
132+
133+
.output-container {
134+
display: flex;
135+
gap: 20px;
136+
margin-top: 20px;
137+
flex-grow: 1;
138+
}
139+
140+
.output {
141+
flex: 1;
142+
background-color: var(--primary-color);
143+
border: 1px solid var(--secondary-color);
144+
border-radius: 8px;
145+
min-height: 100px;
146+
padding: 14px 6px;
147+
white-space: pre-wrap;
148+
overflow-x: auto;
149+
font-family: 'Source Code Pro', 'Consolas', 'Courier New', monospace;
150+
font-size: 13px;
151+
}
152+
153+
.diff-add {
154+
background-color: var(--diff-add);
155+
}
156+
157+
.diff-remove {
158+
background-color: var(--diff-remove);
159+
}
160+
161+
.diff-marker {
162+
font-weight: bold;
163+
margin-left: 5px;
164+
}
165+
166+
.diff-marker-add {
167+
color: #4caf50;
168+
}
169+
170+
.diff-marker-remove {
171+
color: #f44336;
172+
}
173+
174+
.diff-summary {
175+
text-align: center;
176+
margin-top: 20px;
177+
font-size: 18px;
178+
font-family: 'Source Code Pro', monospace;
179+
opacity: 0.3 !important;
180+
font-weight: 500;
181+
}
182+
183+
@keyframes fadeIn {
184+
from {
185+
opacity: 0;
186+
}
187+
188+
to {
189+
opacity: 1;
190+
}
191+
}
192+
193+
.fade-in {
194+
animation: fadeIn 0.5s ease;
195+
}
196+
197+
@media (max-width: 768px) {
198+
199+
.input-container,
200+
.output-container {
201+
flex-direction: column;
202+
}
203+
204+
.controls {
205+
display: block;
206+
}
207+
208+
select {
209+
margin-bottom: 10px;
210+
width: -webkit-fill-available;
211+
}
212+
213+
button {
214+
width: -webkit-fill-available;
215+
}
216+
217+
}

0 commit comments

Comments
 (0)