Spaces:
Sleeping
Sleeping
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Markdown/HTML Converter | PDF & DOCX</title> | |
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> | |
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> | |
<style> | |
:root { | |
--primary-color: #437494; | |
--secondary-color: #29b98b; | |
--accent-color: #7b7ac7; | |
--background-color: #ecf0f1; | |
--text-color: #2c3e50; | |
--card-background: #ffffff; | |
} | |
body { | |
background-color: var(--background-color); | |
color: var(--text-color); | |
} | |
.card { | |
background-color: var(--card-background); | |
border: none; | |
border-radius: 15px; | |
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
} | |
.btn-primary { | |
background-color: var(--primary-color); | |
border-color: var(--primary-color); | |
} | |
.btn-primary:hover { | |
background-color: var(--secondary-color); | |
border-color: var(--secondary-color); | |
} | |
.btn-success { | |
background-color: var(--secondary-color); | |
border-color: var(--secondary-color); | |
} | |
.btn-success:hover { | |
background-color: var(--primary-color); | |
border-color: var(--primary-color); | |
} | |
.btn-warning { | |
background-color: var(--accent-color); | |
border-color: var(--accent-color); | |
color: white; | |
} | |
.btn-warning:hover { | |
background-color: #c0392b; | |
border-color: #c0392b; | |
color: white; | |
} | |
pre { | |
background-color: #f7f9fa; | |
padding: 15px; | |
border-radius: 10px; | |
border: 1px solid #e0e0e0; | |
} | |
.form-control:focus { | |
border-color: var(--primary-color); | |
box-shadow: 0 0 0 0.2rem rgba(52, 152, 219, 0.25); | |
} | |
.fade-enter-active, .fade-leave-active { | |
transition: opacity 0.5s; | |
} | |
.fade-enter-from, .fade-leave-to { | |
opacity: 0; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="app" class="container py-5"> | |
<div class="card p-4 mx-auto mb-5" style="max-width: 800px;"> | |
<h1 class="text-center mb-4" style="color: var(--primary-color);">Markdown/HTML Converter</h1> | |
<label for="inputType" class="form-label mb-0">Input Type:</label> | |
<div class="d-flex align-items-center mb-3"> | |
<div class="me-3 flex-grow-1"> | |
<select id="inputType" v-model="inputType" class="form-select" style="width: 100%;"> | |
<option value="markdown">Markdown</option> | |
<option value="html">HTML</option> | |
</select> | |
</div> | |
<div> | |
<label class="btn btn-primary mb-0"> | |
<i class="fas fa-upload me-2"></i> Upload {{ inputType.toUpperCase() }} File | |
<input type="file" @change="handleFileUpload" :accept="inputType === 'markdown' ? '.md,.markdown' : '.html,.htm'" class="d-none"> | |
</label> | |
</div> | |
</div> | |
<textarea v-model="inputContent" @input="updateCharCount" :placeholder="`Enter your ${inputType} here or upload a file`" class="form-control mb-3" rows="8"></textarea> | |
<div class="text-end text-muted small mb-3">{{ charCount }} / 20000</div> | |
<div v-if="fileName" class="text-center text-muted fst-italic mb-3">{{ fileName }}</div> | |
<div class="d-flex justify-content-center mb-3"> | |
<button @click="convertToPdf" :disabled="isConverting || !inputContent" class="btn btn-success me-2"> | |
<i class="fas fa-file-pdf me-2"></i> Convert to PDF | |
</button> | |
<button @click="convertToDocx" :disabled="isConverting || !inputContent" class="btn btn-primary"> | |
<i class="fas fa-file-word me-2"></i> Convert to DOCX | |
</button> | |
</div> | |
<transition name="fade"> | |
<p v-if="statusMessage" :class="{'text-danger': error, 'text-success': success, 'text-primary': isConverting}" class="mt-3 text-center fw-bold"> | |
{{ statusMessage }} | |
</p> | |
</transition> | |
</div> | |
<!-- API Documentation --> | |
<div class="card p-4 mx-auto mt-5" style="max-width: 800px;"> | |
<h2 class="text-center mb-4" style="color: var(--primary-color);">API Documentation</h2> | |
<button class="btn btn-primary mb-3" @click="toggleApiDocs"> | |
{{ showApiDocs ? 'Hide API Docs' : 'Show API Docs' }} | |
</button> | |
<transition name="fade"> | |
<div v-if="showApiDocs"> | |
<h3 class="mt-4 mb-3">Convert HTML to PDF/DOCX</h3> | |
<p>Endpoint: | |
<code class="bg-light p-1 rounded">{{ selectedApi === 'pdf' ? 'https://pvanand-web-scraping.hf.space/html_to_pdf' : 'https://pvanand-web-scraping.hf.space/convert' }}</code> | |
</p> | |
<p>Method: <code class="bg-light p-1 rounded">POST</code></p> | |
<p>Content-Type: <code class="bg-light p-1 rounded">application/json</code></p> | |
<p>Request Body: | |
<code class="bg-light p-1 rounded">{{ selectedApi === 'pdf' ? '{ "html_content": "Your HTML string here" }' : '{ "html": "Your HTML string here" }' }}</code> | |
</p> | |
<div class="mb-3"> | |
<label for="apiSelect" class="form-label">Select API Example:</label> | |
<select id="apiSelect" v-model="selectedApi" class="form-select"> | |
<option value="pdf">PDF</option> | |
<option value="docx">DOCX</option> | |
</select> | |
</div> | |
<div class="mb-3"> | |
<label for="languageSelect" class="form-label">Select Language:</label> | |
<select id="languageSelect" v-model="selectedLanguage" class="form-select"> | |
<option value="python">Python</option> | |
<option value="curl">cURL</option> | |
<option value="javascript">JavaScript</option> | |
</select> | |
</div> | |
<pre v-if="selectedLanguage === 'python'"> | |
import requests | |
import json | |
url = "{{ selectedApi === 'pdf' ? 'https://pvanand-web-scraping.hf.space/html_to_pdf' : 'https://pvanand-web-scraping.hf.space/convert' }}" | |
payload = json.dumps({ | |
"{{ selectedApi === 'pdf' ? 'html_content' : 'html' }}": "<h1>Hello, World!</h1>" | |
}) | |
headers = { | |
'Content-Type': 'application/json' | |
} | |
response = requests.post(url, headers=headers, data=payload) | |
with open('output.{{ selectedApi }}', 'wb') as f: | |
f.write(response.content) | |
</pre> | |
<pre v-if="selectedLanguage === 'curl'"> | |
curl -X POST '{{ selectedApi === 'pdf' ? 'https://pvanand-web-scraping.hf.space/html_to_pdf' : 'https://pvanand-web-scraping.hf.space/convert' }}' \ | |
-H 'Content-Type: application/json' \ | |
-d '{"{{ selectedApi === 'pdf' ? 'html_content' : 'html' }}": "<h1>Hello, World!</h1>"}' \ | |
--output output.{{ selectedApi }} | |
</pre> | |
<pre v-if="selectedLanguage === 'javascript'"> | |
fetch('{{ selectedApi === 'pdf' ? 'https://pvanand-web-scraping.hf.space/html_to_pdf' : 'https://pvanand-web-scraping.hf.space/convert' }}', { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
body: JSON.stringify({ | |
{{ selectedApi === 'pdf' ? 'html_content' : 'html' }}: '<h1>Hello, World!</h1>' | |
}), | |
}) | |
.then(response => response.blob()) | |
.then(blob => { | |
const url = window.URL.createObjectURL(blob); | |
const a = document.createElement('a'); | |
a.style.display = 'none'; | |
a.href = url; | |
a.download = 'output.{{ selectedApi }}'; | |
document.body.appendChild(a); | |
a.click(); | |
window.URL.revokeObjectURL(url); | |
}) | |
.catch((error) => console.error('Error:', error)); | |
</pre> | |
</div> | |
</transition> | |
</div> | |
</div> | |
<script> | |
const { createApp, ref, computed } = Vue; | |
createApp({ | |
setup() { | |
const inputContent = ref(''); | |
const inputType = ref('markdown'); | |
const error = ref(false); | |
const success = ref(false); | |
const isConverting = ref(false); | |
const fileName = ref(''); | |
const showApiDocs = ref(false); | |
const selectedApi = ref('pdf'); | |
const selectedLanguage = ref('python'); | |
const charCount = computed(() => inputContent.value.length); | |
const statusMessage = ref(''); | |
const updateCharCount = () => { | |
if (inputContent.value.length > 20000) { | |
inputContent.value = inputContent.value.slice(0, 20000); | |
} | |
}; | |
const handleFileUpload = (event) => { | |
const file = event.target.files[0]; | |
if (file) { | |
fileName.value = file.name; | |
const reader = new FileReader(); | |
reader.onload = (e) => { | |
inputContent.value = e.target.result; | |
updateCharCount(); | |
}; | |
reader.readAsText(file); | |
} | |
}; | |
const convertToPdf = async () => { | |
await convert('pdf'); | |
}; | |
const convertToDocx = async () => { | |
await convert('docx'); | |
}; | |
const convert = async (type) => { | |
error.value = false; | |
success.value = false; | |
isConverting.value = true; | |
statusMessage.value = 'Converting... Please wait.'; | |
const url = type === 'pdf' | |
? 'https://pvanand-web-scraping.hf.space/html_to_pdf' | |
: 'https://pvanand-web-scraping.hf.space/convert'; | |
const paramName = type === 'pdf' ? 'html_content' : 'html'; | |
const filename = `converted.${type}`; | |
const mimeType = type === 'pdf' | |
? 'application/pdf' | |
: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; | |
try { | |
let htmlContent = inputContent.value; | |
if (inputType.value === 'markdown') { | |
// Use marked.parse() to convert Markdown to HTML | |
htmlContent = marked.parse(inputContent.value); | |
} | |
const response = await axios.post(url, { | |
[paramName]: htmlContent | |
}, { responseType: 'blob' }); | |
const blob = new Blob([response.data], { type: mimeType }); | |
const link = document.createElement('a'); | |
link.href = URL.createObjectURL(blob); | |
link.download = filename; | |
link.click(); | |
URL.revokeObjectURL(link.href); | |
success.value = true; | |
statusMessage.value = `Successfully converted to ${type.toUpperCase()}!`; | |
} catch (e) { | |
error.value = true; | |
statusMessage.value = `Error converting to ${type.toUpperCase()}. Please try again.`; | |
console.error('Error:', e); | |
} finally { | |
isConverting.value = false; | |
} | |
}; | |
const toggleApiDocs = () => { | |
showApiDocs.value = !showApiDocs.value; | |
}; | |
return { | |
inputContent, | |
inputType, | |
charCount, | |
fileName, | |
statusMessage, | |
isConverting, | |
error, | |
success, | |
showApiDocs, | |
selectedApi, | |
selectedLanguage, | |
updateCharCount, | |
handleFileUpload, | |
convertToPdf, | |
convertToDocx, | |
toggleApiDocs | |
}; | |
} | |
}).mount('#app'); | |
</script> | |
<script src="https://kit.fontawesome.com/your-fontawesome-kit.js" crossorigin="anonymous"></script> | |
</body> | |
</html> |