Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions terminal-to-html.html
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,69 @@ <h1>Terminal to HTML</h1>
return div.innerHTML;
}

function findDuplicateBlocks(html, minLines = 10) {
const lines = html.split('\n');
const duplicates = [];

// Find all duplicate blocks of minLines or more consecutive lines
for (let blockSize = minLines; blockSize <= Math.floor(lines.length / 2); blockSize++) {
for (let i = 0; i <= lines.length - blockSize; i++) {
const block = lines.slice(i, i + blockSize).join('\n');

// Check if this block appears later in the content
for (let j = i + blockSize; j <= lines.length - blockSize; j++) {
const compareBlock = lines.slice(j, j + blockSize).join('\n');

if (block === compareBlock) {
// Check if this duplicate is already tracked or overlaps with a larger one
const isDuplicate = duplicates.some(d =>
(j >= d.startLine && j < d.startLine + d.lineCount) ||
(j + blockSize > d.startLine && j < d.startLine + d.lineCount)
);

if (!isDuplicate) {
duplicates.push({
startLine: j,
lineCount: blockSize,
originalStartLine: i
});
}
}
}
}
}

// Sort by start line descending (so we can remove from end to beginning)
duplicates.sort((a, b) => b.startLine - a.startLine);

// Merge overlapping duplicates, keeping the larger ones
const merged = [];
for (const dup of duplicates) {
const overlaps = merged.some(m =>
(dup.startLine >= m.startLine && dup.startLine < m.startLine + m.lineCount) ||
(dup.startLine + dup.lineCount > m.startLine && dup.startLine < m.startLine + m.lineCount)
);
if (!overlaps) {
merged.push(dup);
}
}

return merged;
}

function removeDuplicateBlocks(html, duplicates) {
const lines = html.split('\n');

// Sort duplicates by startLine descending to remove from end first
const sortedDups = [...duplicates].sort((a, b) => b.startLine - a.startLine);

for (const dup of sortedDups) {
lines.splice(dup.startLine, dup.lineCount);
}

return lines.join('\n');
}

function wrapInHtmlDocument(content) {
return `<!DOCTYPE html>
<html lang="en">
Expand Down Expand Up @@ -641,6 +704,7 @@ <h1>Terminal to HTML</h1>
<h2>HTML Code</h2>
<div class="button-group">
<button id="copyHtmlBtn">Copy HTML</button>
<button id="deduplicateBtn" style="display: none;"></button>
<span id="authLinkContainer" style="display: none;">
<button id="authLink">Authenticate with GitHub</button>
</span>
Expand Down Expand Up @@ -687,6 +751,34 @@ <h2>HTML Code</h2>

checkGithubAuth();

// Check for duplicate blocks and show deduplicate button if found
const deduplicateBtn = document.getElementById('deduplicateBtn');
let currentDuplicates = findDuplicateBlocks(fullHtml);

if (currentDuplicates.length > 0) {
deduplicateBtn.textContent = `Remove ${currentDuplicates.length} duplicate block${currentDuplicates.length > 1 ? 's' : ''}`;
deduplicateBtn.style.display = 'inline-block';
}

deduplicateBtn.addEventListener('click', () => {
fullHtml = removeDuplicateBlocks(fullHtml, currentDuplicates);
htmlOutputTextarea.value = fullHtml;

// Update preview
const previewContainer = document.querySelector('.preview-container');
if (previewContainer) {
previewContainer.innerHTML = fullHtml;
}

// Re-check for remaining duplicates
currentDuplicates = findDuplicateBlocks(fullHtml);
if (currentDuplicates.length > 0) {
deduplicateBtn.textContent = `Remove ${currentDuplicates.length} duplicate block${currentDuplicates.length > 1 ? 's' : ''}`;
} else {
deduplicateBtn.style.display = 'none';
}
});

// Create preview section
const previewSection = document.createElement('div');
previewSection.className = 'section';
Expand Down