debrid-services-comparison/gui.html
2025-01-11 09:44:58 +05:00

423 lines
No EOL
12 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Markdown/JSON Toolkit</title>
<style>
/* style.css */
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 20px;
background-color: #f4f4f8;
color: #333;
line-height: 1.6;
}
header {
text-align: center;
margin-bottom: 20px;
}
h1 {
color: #007bff;
margin-bottom: 0.5em;
}
nav {
display: flex;
justify-content: center;
gap: 10px;
margin-top: 1em;
}
.tab-button {
padding: 0.75em 1.5em;
background-color: #f9f9f9;
border: 1px solid #ddd;
border-bottom: none;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
cursor: pointer;
transition: background-color 0.3s ease-in-out, transform 0.2s;
color: #333;
}
.tab-button.active {
background-color: #fff;
border-bottom: 2px solid #007bff;
}
.tab-button:hover {
background-color: #eee;
transform: translateY(-2px);
}
main {
max-width: 1200px;
margin: 0 auto;
background-color: #fff;
padding: 30px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
h2 {
color: #333;
margin-bottom: 1em;
}
p {
color: #555;
margin-bottom: 1em;
}
textarea {
width: calc(100% - 16px);
min-height: 150px;
padding: 0.75em;
margin-bottom: 1.5em;
border: 1px solid #ddd;
border-radius: 6px;
box-sizing: border-box;
font-size: 1rem;
font-family: 'Courier New', monospace;
transition: border-color 0.3s ease-in-out, box-shadow 0.3s;
}
textarea:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 5px rgba(0, 123, 255, 0.2);
}
.input-group {
margin-bottom: 1.5em;
}
label {
display: block;
margin-bottom: 0.5em;
font-weight: bold;
}
input[type="text"] {
width: calc(100% - 12px);
padding: 0.75em;
border: 1px solid #ddd;
border-radius: 6px;
box-sizing: border-box;
font-size: 1rem;
transition: border-color 0.3s ease-in-out, box-shadow 0.3s;
}
input[type="text"]:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 5px rgba(0, 123, 255, 0.2);
}
button {
padding: 0.75em 1.5em;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.3s ease-in-out, transform 0.2s;
}
button:hover {
background-color: #0056b3;
transform: translateY(-2px);
}
.output-area {
margin-top: 2em;
padding: 1em;
border: 1px solid #eee;
border-radius: 6px;
background-color: #f9f9f9;
}
h3 {
margin-top: 0;
color: #333;
margin-bottom: 0.75em;
}
pre {
white-space: pre-wrap;
font-family: 'Courier New', monospace;
font-size: 0.9rem;
color: #222;
line-height: 1.4;
margin: 0;
}
.copy-button {
margin-top: 0.75em;
background-color: #28a745;
color: #fff;
transition: background-color 0.3s ease-in-out, transform 0.2s;
}
.copy-button:hover {
background-color: #218838;
transform: translateY(-2px);
}
</style>
</head>
<body>
<header>
<h1>Markdown/JSON Toolkit</h1>
<nav>
<button class="tab-button active" data-tab="markdownToJson">Markdown to JSON</button>
<button class="tab-button" data-tab="jsonUpdate">Update JSON</button>
<button class="tab-button" data-tab="jsonToMarkdown">JSON to Markdown</button>
</nav>
</header>
<main>
<section id="markdownToJson" class="tab-content active">
<h2>Markdown to JSON</h2>
<p>Paste your GitHub flavored Markdown table here:</p>
<textarea id="markdownInput" placeholder="Paste Markdown table"></textarea>
<button id="convertToJsonBtn">Convert to JSON</button>
<aside class="output-area">
<h3>JSON Output</h3>
<pre id="jsonOutput"></pre>
<button id="selectJsonBtn" class="copy-button" style="display: none;">Select All</button>
</aside>
</section>
<section id="jsonUpdate" class="tab-content">
<h2>Update JSON</h2>
<p>Paste your existing JSON data here:</p>
<textarea id="existingJsonInput" placeholder="Paste existing JSON"></textarea>
<div class="input-group">
<label for="newProviderName">New Debrid Provider Name:</label>
<input type="text" id="newProviderName" placeholder="New Provider Name">
</div>
<div class="input-group">
<label for="supportedServices">Supported Services (comma-separated):</label>
<input type="text" id="supportedServices" placeholder="e.g., 1Fichier, 4Shared">
</div>
<button id="updateJsonBtn">Update JSON</button>
<aside class="output-area">
<h3>Updated JSON Output</h3>
<pre id="updatedJsonOutput"></pre>
<button id="selectUpdatedJsonBtn" class="copy-button" style="display: none;">Select All</button>
</aside>
</section>
<section id="jsonToMarkdown" class="tab-content">
<h2>JSON to Markdown</h2>
<p>Paste your JSON data here:</p>
<textarea id="inputJsonForMarkdown" placeholder="Paste JSON data"></textarea>
<button id="convertToMarkdownBtn">Convert to Markdown Table</button>
<aside class="output-area">
<h3>Markdown Table Output</h3>
<pre id="markdownOutput"></pre>
<button id="selectMarkdownBtn" class="copy-button" style="display: none;">Select All</button>
</aside>
</section>
</main>
<script>
/* script.js */
const tabButtons = document.querySelectorAll('.tab-button');
const tabContents = document.querySelectorAll('.tab-content');
const markdownInput = document.getElementById('markdownInput');
const convertToJsonBtn = document.getElementById('convertToJsonBtn');
const jsonOutput = document.getElementById('jsonOutput');
const selectJsonBtn = document.getElementById('selectJsonBtn');
const existingJsonInput = document.getElementById('existingJsonInput');
const newProviderNameInput = document.getElementById('newProviderName');
const supportedServicesInput = document.getElementById('supportedServices');
const updateJsonBtn = document.getElementById('updateJsonBtn');
const updatedJsonOutput = document.getElementById('updatedJsonOutput');
const selectUpdatedJsonBtn = document.getElementById('selectUpdatedJsonBtn');
const inputJsonForMarkdown = document.getElementById('inputJsonForMarkdown');
const convertToMarkdownBtn = document.getElementById('convertToMarkdownBtn');
const markdownOutput = document.getElementById('markdownOutput');
const selectMarkdownBtn = document.getElementById('selectMarkdownBtn');
let currentJSON = {};
// Helper function to activate a tab
const activateTab = (tabId) => {
tabContents.forEach(content => content.classList.remove('active'));
tabButtons.forEach(button => button.classList.remove('active'));
document.getElementById(tabId).classList.add('active');
document.querySelector(`.tab-button[data-tab="${tabId}"]`).classList.add('active');
};
// Event listeners for tab clicks
tabButtons.forEach(button => {
button.addEventListener('click', (event) => {
activateTab(event.target.dataset.tab);
});
});
// Markdown to JSON functionality
convertToJsonBtn.addEventListener('click', () => {
const markdownText = markdownInput.value.trim();
if (!markdownText) {
jsonOutput.textContent = "Please paste a Markdown table.";
selectJsonBtn.style.display = 'none';
return;
}
const lines = markdownText.split('\n').map(line => line.trim());
if (lines.length < 2) {
jsonOutput.textContent = "Invalid Markdown table.";
selectJsonBtn.style.display = 'none';
return;
}
const [headerLine, ...dataLines] = lines;
const headersWithBold = headerLine.split('|').map(h => h.trim()).filter(Boolean);
const headers = headersWithBold.slice(1).map(h => h.replace(/\*\*/g, ''));
const jsonData = {};
dataLines.forEach(line => {
if (line.startsWith('|') && !line.includes('-')) {
const cellsWithBold = line.split('|').map(c => c.trim()).filter(Boolean);
if (cellsWithBold.length > 0) {
const host = cellsWithBold[0].replace(/\*\*/g, '');
jsonData[host] = {};
for (let i = 1; i < cellsWithBold.length; i++) {
jsonData[host][headers[i - 1]] = cellsWithBold[i].toLowerCase() === 'yes' ? 'yes' : 'no';
}
}
}
});
currentJSON = jsonData;
jsonOutput.textContent = JSON.stringify(currentJSON, null, 2);
selectJsonBtn.style.display = 'block';
});
// Update JSON functionality
updateJsonBtn.addEventListener('click', () => {
const jsonInputValue = existingJsonInput.value.trim();
const newProviderName = newProviderNameInput.value.trim();
const supportedServicesInputVal = supportedServicesInput.value.trim();
const supportedServicesList = supportedServicesInputVal.split(',').map(s => s.trim());
let baseJSON = currentJSON;
if (jsonInputValue) {
try {
baseJSON = JSON.parse(jsonInputValue);
} catch (error) {
updatedJsonOutput.textContent = "Invalid JSON format.";
selectUpdatedJsonBtn.style.display = 'none';
return;
}
}
if (!newProviderName || !supportedServicesInputVal) {
updatedJsonOutput.textContent = "Please enter the new provider name and supported services.";
selectUpdatedJsonBtn.style.display = 'none';
return;
}
const updatedJSON = { ...baseJSON };
for (const serviceName in updatedJSON) {
updatedJSON[serviceName][newProviderName] = supportedServicesList.includes(serviceName) ? 'yes' : 'no';
}
supportedServicesList.forEach(service => {
if (!updatedJSON.hasOwnProperty(service)) {
updatedJSON[service] = {};
for (const existingService in baseJSON) {
for (const provider in baseJSON[existingService]) {
if (!updatedJSON[service].hasOwnProperty(provider)) {
updatedJSON[service][provider] = 'no';
}
}
break;
}
updatedJSON[service][newProviderName] = 'yes';
}
});
currentJSON = updatedJSON;
updatedJsonOutput.textContent = JSON.stringify(currentJSON, null, 2);
selectUpdatedJsonBtn.style.display = 'block';
});
// JSON to Markdown functionality
convertToMarkdownBtn.addEventListener('click', () => {
const jsonString = inputJsonForMarkdown.value.trim();
let jsonData = currentJSON; // Default to currentJSON if input is empty
if (jsonString) {
try {
jsonData = JSON.parse(jsonString);
} catch (error) {
markdownOutput.textContent = "Invalid JSON format.";
selectMarkdownBtn.style.display = 'none';
return;
}
}
if (!jsonData || Object.keys(jsonData).length === 0) {
markdownOutput.textContent = "JSON data is empty.";
selectMarkdownBtn.style.display = 'none';
return;
}
const services = Object.keys(jsonData);
const firstService = jsonData[services[0]];
const providers = Object.keys(firstService);
let markdownTable = `| **Service Name** | ${providers.map(p => `**${p}**`).join(' | ')} |\n`;
markdownTable += `| ----------------- | ${providers.map(() => '---------------').join(' | ')} |\n`;
markdownTable += services.map(service => {
const row = `| **${service}** | ${providers.map(provider => jsonData[service][provider].charAt(0).toUpperCase() + jsonData[service][provider].slice(1)).join(' | ')} |`;
return row;
}).join('\n');
markdownOutput.textContent = markdownTable;
selectMarkdownBtn.style.display = 'block';
});
// Select all output functionality
const selectAllOutput = (outputElement) => {
const range = document.createRange();
range.selectNodeContents(outputElement);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
document.execCommand('copy');
selection.removeAllRanges();
alert('Output copied to clipboard!');
};
selectJsonBtn.addEventListener('click', () => selectAllOutput(jsonOutput));
selectUpdatedJsonBtn.addEventListener('click', () => selectAllOutput(updatedJsonOutput));
selectMarkdownBtn.addEventListener('click', () => selectAllOutput(markdownOutput));
// Initialize the first tab as active
activateTab('markdownToJson');
</script>
</body>
</html>