Skip to content

Instantly share code, notes, and snippets.

@taroyanaka
Created July 20, 2024 22:28
Show Gist options
  • Save taroyanaka/d6632da847636acbe6f4f47b4217deb5 to your computer and use it in GitHub Desktop.
Save taroyanaka/d6632da847636acbe6f4f47b4217deb5 to your computer and use it in GitHub Desktop.
compare_text.html, text differ, work only this HTML file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>compare text</title>
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.45/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/localforage@1.10.0/dist/localforage.min.js"></script>
<!-- <script src="./lib/vue@3.2.36.global.prod.js"></script> -->
<!-- <script src="./lib/localforage@1.10.0.js"></script> -->
<style>
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
font-family: Arial, sans-serif;
}
.container {
background: #fff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width: 80%;
max-width: 800px;
position: relative;
}
textarea {
width: 100%;
height: 150px;
margin-bottom: 20px;
padding: 10px;
box-sizing: border-box;
border-radius: 5px;
border: 1px solid #ccc;
font-size: 16px;
resize: none;
}
.diff-output {
white-space: pre-wrap;
font-size: 16px;
margin-top: 20px;
}
.highlight {
background-color: #ADD8E6;
}
.deleted {
color: red;
text-decoration: line-through;
}
.added {
color: blue;
}
button {
margin-bottom: 10px;
padding: 0.5rem 1rem;
font-size: 1rem;
border: none;
border-radius: 5px;
background-color: #007bff;
color: white;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
.compare-btn-container {
position: absolute;
bottom: 20px;
right: 20px;
}
.compare-btn-container button {
padding: 0.75rem 1.5rem; /* Increased padding */
font-size: 1.5rem; /* Increased font size */
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div id="app" class="container">
<button @click="toggleText1Visibility">{{ text1Visible ? 'Hide' : 'Show' }} Text 1</button>
<textarea v-if="text1Visible" v-model="text1" placeholder="text 1"></textarea>
<textarea v-model="text2" placeholder="text 2"></textarea>
<input v-model="pairName" placeholder="Pair name">
<button v-if="pairName" @click="savePair">Save Pair</button>
<select v-model="selectedPair" @change="loadSelectedPair">
<option v-for="pair in pairList" :key="pair.name" :value="pair.name">{{ pair.name }}</option>
</select>
<button v-if="selectedPair" @click="deletePair">Delete Selected Pair</button>
<div class="diff-output" ref="diffOutput">
<div v-for="(line, index) in diff" :key="index">
{{ index + 1 }}:
<span v-for="(part, partIndex) in line.parts" :key="partIndex" :class="part.class">
{{ part.text }}
</span>
</div>
</div>
<div class="compare-btn-container">
<button @click="compareTexts">Compare</button>
</div>
</div>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const text1 = ref(`I stepped on the cat,
It didn't like that,
And now it's gone away.
猫ネコ猫ねこ🐈`);
const text2 = ref(`I stepped on the dog,
It didn't hate that,
And now it's gone away.
猫ネコ犬🐕ねこ🐕`);
const diff = ref([]);
const text1Visible = ref(true);
const pairName = ref('');
const pairList = ref([]);
const selectedPair = ref('');
const toggleText1Visibility = () => {
text1Visible.value = !text1Visible.value;
};
const compareTexts = () => {
const lines1 = text1.value.split('\n');
const lines2 = text2.value.split('\n');
diff.value = [];
const maxLines = Math.max(lines1.length, lines2.length);
for (let i = 0; i < maxLines; i++) {
const line1 = lines1[i] || '';
const line2 = lines2[i] || '';
if (line1 !== line2) {
diff.value.push({
parts: generateDiffParts(line1, line2)
});
} else {
diff.value.push({
parts: [{ text: line1, class: '' }]
});
}
}
};
const generateDiffParts = (line1, line2) => {
const parts1 = line1.split(/(\s+)/); // Split by spaces, keeping spaces
const parts2 = line2.split(/(\s+)/); // Split by spaces, keeping spaces
const maxParts = Math.max(parts1.length, parts2.length);
const result = [];
for (let i = 0; i < maxParts; i++) {
const part1 = parts1[i] || '';
const part2 = parts2[i] || '';
if (part1 !== part2) {
if (part1) result.push({ text: part1, class: 'deleted' });
if (part2) result.push({ text: part2, class: 'added' });
} else {
result.push({ text: part1 || part2, class: '' });
}
}
return result;
};
const savePair = async () => {
if (!pairName.value.trim()) {
alert('Please enter a name for the pair.');
return;
}
const pairData = {
text1: text1.value,
text2: text2.value
};
await localforage.setItem(pairName.value, pairData);
await loadPairs(); // Refresh pair list
pairName.value = ''; // Clear the input field
};
const loadPairs = async () => {
pairList.value = [];
const keys = await localforage.keys();
pairList.value = keys.map(key => ({ name: key }));
};
const loadSelectedPair = async () => {
if (!selectedPair.value) return;
const pairData = await localforage.getItem(selectedPair.value);
if (pairData) {
text1.value = pairData.text1;
text2.value = pairData.text2;
}
};
const deletePair = async () => {
if (!selectedPair.value) {
alert('Please select a pair to delete.');
return;
}
await localforage.removeItem(selectedPair.value);
await loadPairs(); // Refresh pair list
selectedPair.value = ''; // Clear the selection
text1.value = '';
text2.value = '';
};
// Load pairs on startup
loadPairs();
return {
text1,
text2,
diff,
text1Visible,
pairName,
pairList,
selectedPair,
toggleText1Visibility,
compareTexts,
savePair,
loadPairs,
loadSelectedPair,
deletePair
};
}
}).mount('#app');
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment