anycoder-30a78234 / index.html
york's picture
Upload folder using huggingface_hub
3e6ec56 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modern Markdown Previewer</title>
<!-- Import Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<!-- Import FontAwesome for Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Highlight.js CSS for Syntax Highlighting -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-dark.min.css">
<style>
/* --- CSS VARIABLES & THEME CONFIGURATION --- */
:root {
--primary-color: #3b82f6;
--primary-hover: #2563eb;
--bg-body: #f3f4f6;
--bg-panel: #ffffff;
--text-main: #1f2937;
--text-muted: #6b7280;
--border-color: #e5e7eb;
--code-bg: #f8fafc;
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--radius-md: 0.5rem;
--radius-lg: 0.75rem;
--header-height: 60px;
--transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
[data-theme="dark"] {
--bg-body: #0f172a;
--bg-panel: #1e293b;
--text-main: #f1f5f9;
--text-muted: #94a3b8;
--border-color: #334155;
--code-bg: #0d1117;
--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.5);
}
/* --- RESET & BASE STYLES --- */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Inter', sans-serif;
background-color: var(--bg-body);
color: var(--text-main);
height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden; /* Prevent body scroll, handle inside panels */
transition: background-color 0.3s ease, color 0.3s ease;
}
/* --- HEADER --- */
header {
height: var(--header-height);
background-color: var(--bg-panel);
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 1.5rem;
box-shadow: var(--shadow-sm);
z-index: 10;
}
.brand {
display: flex;
align-items: center;
gap: 0.75rem;
font-weight: 700;
font-size: 1.1rem;
color: var(--text-main);
text-decoration: none;
}
.brand i {
color: var(--primary-color);
}
.header-actions {
display: flex;
align-items: center;
gap: 1rem;
}
.btn-icon {
background: transparent;
border: 1px solid var(--border-color);
color: var(--text-muted);
width: 36px;
height: 36px;
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: var(--transition);
font-size: 1rem;
}
.btn-icon:hover {
background-color: var(--code-bg);
color: var(--primary-color);
border-color: var(--primary-color);
}
.btn-primary {
background-color: var(--primary-color);
color: white;
border: none;
padding: 0.5rem 1rem;
border-radius: var(--radius-md);
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
transition: var(--transition);
font-size: 0.9rem;
}
.btn-primary:hover {
background-color: var(--primary-hover);
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);
}
/* --- MAIN LAYOUT --- */
main {
flex: 1;
display: grid;
grid-template-columns: 1fr 1fr;
height: calc(100vh - var(--header-height));
overflow: hidden;
}
/* --- EDITOR PANEL --- */
.editor-container {
display: flex;
flex-direction: column;
border-right: 1px solid var(--border-color);
background-color: var(--bg-panel);
position: relative;
}
.panel-header {
padding: 0.75rem 1rem;
border-bottom: 1px solid var(--border-color);
display: flex;
justify-content: space-between;
align-items: center;
background-color: rgba(255, 255, 255, 0.5);
backdrop-filter: blur(4px);
font-size: 0.85rem;
font-weight: 600;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.editor-wrapper {
flex: 1;
position: relative;
}
#markdown-input {
width: 100%;
height: 100%;
border: none;
resize: none;
padding: 1.5rem;
font-family: 'JetBrains Mono', monospace;
font-size: 0.95rem;
line-height: 1.6;
background-color: var(--bg-panel);
color: var(--text-main);
outline: none;
}
/* --- PREVIEW PANEL --- */
.preview-container {
background-color: var(--bg-body);
overflow-y: auto;
position: relative;
}
#preview-output {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
background-color: var(--bg-panel);
min-height: 100%;
box-shadow: var(--shadow-sm);
border-top: 1px solid var(--border-color);
border-bottom: 1px solid var(--border-color);
}
/* --- MARKDOWN STYLING (Inside Preview) --- */
#preview-output h1, #preview-output h2, #preview-output h3 {
margin-top: 1.5rem;
margin-bottom: 0.75rem;
line-height: 1.2;
color: var(--text-main);
}
#preview-output h1 { font-size: 2.25rem; font-weight: 800; border-bottom: 2px solid var(--border-color); padding-bottom: 0.5rem; }
#preview-output h2 { font-size: 1.75rem; font-weight: 700; border-bottom: 1px solid var(--border-color); padding-bottom: 0.25rem; }
#preview-output h3 { font-size: 1.35rem; font-weight: 600; }
#preview-output p {
margin-bottom: 1rem;
line-height: 1.7;
color: var(--text-main);
}
#preview-output ul, #preview-output ol {
margin-bottom: 1rem;
padding-left: 1.5rem;
}
#preview-output li {
margin-bottom: 0.25rem;
line-height: 1.6;
}
#preview-output code {
font-family: 'JetBrains Mono', monospace;
font-size: 0.9em;
background-color: rgba(59, 130, 246, 0.1);
color: var(--primary-color);
padding: 0.2em 0.4em;
border-radius: 4px;
}
#preview-output pre {
background-color: var(--code-bg);
padding: 1rem;
border-radius: var(--radius-md);
overflow-x: auto;
margin-bottom: 1rem;
border: 1px solid var(--border-color);
}
#preview-output pre code {
background-color: transparent;
color: inherit;
padding: 0;
}
#preview-output blockquote {
border-left: 4px solid var(--primary-color);
padding-left: 1rem;
margin: 1rem 0;
color: var(--text-muted);
font-style: italic;
background: rgba(59, 130, 246, 0.05);
padding-top: 0.5rem;
padding-bottom: 0.5rem;
border-radius: 0 4px 4px 0;
}
#preview-output a {
color: var(--primary-color);
text-decoration: none;
font-weight: 500;
}
#preview-output a:hover {
text-decoration: underline;
}
#preview-output img {
max-width: 100%;
border-radius: var(--radius-md);
box-shadow: var(--shadow-md);
margin: 1rem 0;
}
#preview-output hr {
border: 0;
height: 1px;
background-image: linear-gradient(to right, rgba(0, 0, 0, 0), var(--border-color), rgba(0, 0, 0, 0));
margin: 2rem 0;
}
/* --- TOAST NOTIFICATION --- */
.toast {
position: fixed;
bottom: 2rem;
left: 50%;
transform: translateX(-50%) translateY(100px);
background-color: var(--text-main);
color: var(--bg-panel);
padding: 0.75rem 1.5rem;
border-radius: 50px;
box-shadow: var(--shadow-md);
opacity: 0;
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
z-index: 100;
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.9rem;
}
.toast.show {
transform: translateX(-50%) translateY(0);
opacity: 1;
}
/* --- RESPONSIVE DESIGN --- */
@media (max-width: 768px) {
main {
grid-template-columns: 1fr;
grid-template-rows: 1fr 1fr;
}
.editor-container {
border-right: none;
border-bottom: 1px solid var(--border-color);
}
#preview-output {
padding: 1rem;
}
}
</style>
</head>
<body>
<!-- Header Section -->
<header>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="brand">
<i class="fa-solid fa-code"></i>
AnyCoder <span style="font-weight: 300; opacity: 0.7;">| Markdown Preview</span>
</a>
<div class="header-actions">
<button class="btn-icon" id="theme-toggle" title="Toggle Dark Mode">
<i class="fa-solid fa-moon"></i>
</button>
<button class="btn-icon" id="reset-btn" title="Reset Content">
<i class="fa-solid fa-rotate-right"></i>
</button>
<button class="btn-primary" id="download-btn">
<i class="fa-solid fa-download"></i> Download
</button>
</div>
</header>
<!-- Main Content Area -->
<main>
<!-- Editor Panel -->
<section class="editor-container">
<div class="panel-header">
<span><i class="fa-solid fa-pen-nib"></i> Input Markdown</span>
<span id="char-count">0 chars</span>
</div>
<div class="editor-wrapper">
<textarea id="markdown-input" spellcheck="false" placeholder="Type your markdown here..."># Hello World!
Welcome to this **Modern Markdown Previewer**.
## Features
- **Real-time** preview
- **Syntax Highlighting** for code
- **Dark Mode** support
- **Responsive** layout
### Example Code Block
\`\`\`javascript
function sayHello() {
console.log("Hello, AnyCoder!");
}
\`\`\`
> "The best way to predict the future is to create it." - Peter Drucker
[Click here for Hugging Face](https://huggingface.co/spaces/akhaliq/anycoder)
"></textarea>
</div>
</section>
<!-- Preview Panel -->
<section class="preview-container">
<div class="panel-header">
<span><i class="fa-solid fa-eye"></i> Live Preview</span>
</div>
<div id="preview-output"></div>
</section>
</main>
<!-- Toast Notification -->
<div id="toast" class="toast">
<i class="fa-solid fa-check-circle"></i> <span id="toast-message">Action Successful</span>
</div>
<!-- Highlight.js Library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
<script>
/**
* AnyCoder Markdown Previewer Logic
* Handles Markdown parsing, Syntax Highlighting, Theming, and Interactions
*/
// DOM Elements
const input = document.getElementById('markdown-input');
const output = document.getElementById('preview-output');
const themeToggle = document.getElementById('theme-toggle');
const resetBtn = document.getElementById('reset-btn');
const downloadBtn = document.getElementById('download-btn');
const charCount = document.getElementById('char-count');
const toast = document.getElementById('toast');
const toastMsg = document.getElementById('toast-message');
// Default Content
const defaultContent = `# Hello World!
Welcome to this **Modern Markdown Previewer**.
## Features
- **Real-time** preview
- **Syntax Highlighting** for code
- **Dark Mode** support
- **Responsive** layout
### Example Code Block
\`\`\`javascript
function sayHello() {
console.log("Hello, AnyCoder!");
}
\`\`\`
> "The best way to predict the future is to create it." - Peter Drucker
[Click here for Hugging Face](https://huggingface.co/spaces/akhaliq/anycoder)
`;
// --- Core Markdown Parser ---
// A simple, lightweight regex-based parser to avoid heavy external dependencies like marked.js
function parseMarkdown(text) {
let html = text;
// Escape HTML (Basic sanitization)
html = html.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
// Headers (H1 - H6)
html = html.replace(/^###### (.*$)/gim, '<h6>$1</h6>');
html = html.replace(/^##### (.*$)/gim, '<h5>$1</h5>');
html = html.replace(/^#### (.*$)/gim, '<h4>$1</h4>');
html = html.replace(/^### (.*$)/gim, '<h3>$1</h3>');
html = html.replace(/^## (.*$)/gim, '<h2>$1</h2>');
html = html.replace(/^# (.*$)/gim, '<h1>$1</h1>');
// Bold and Italic
html = html.replace(/\*\*\*(.*)\*\*\*/gim, '<strong><em>$1</em></strong>');
html = html.replace(/\*\*(.*)\*\*/gim, '<strong>$1</strong>');
html = html.replace(/\*(.*)\*/gim, '<em>$1</em>');
html = html.replace(/___(.*)___/gim, '<strong><em>$1</em></strong>');
html = html.replace(/__(.*)__/gim, '<strong>$1</strong>');
html = html.replace(/_(.*)_/gim, '<em>$1</em>');
// Blockquotes
html = html.replace(/^\> (.*$)/gim, '<blockquote>$1</blockquote>');
// Images
html = html.replace(/!\[(.*?)\]\((.*?)\)/gim, "<img alt='$1' src='$2' />");
// Links
html = html.replace(/\[(.*?)\]\((.*?)\)/gim, "<a href='$2' target='_blank'>$1</a>");
// Code Blocks (Pre/Code)
html = html.replace(/```([\s\S]*?)```/gim, "<pre><code class='language-js'>$1</code></pre>");
// Inline Code
html = html.replace(/`(.*)`/gim, "<code>$1</code>");
// Horizontal Rule
html = html.replace(/^---$/gim, '<hr>');
// Unordered Lists
html = html.replace(/^\s*-\s(.*$)/gim, '<ul><li>$1</li></ul>');
// Clean up consecutive uls
html = html.replace(/<\/ul>\s*<ul>/gim, '');
// Ordered Lists
html = html.replace(/^\s*\d+\.\s(.*$)/gim, '<ol><li>$1</li></ol>');
// Clean up consecutive ols
html = html.replace(/<\/ol>\s*<ol>/gim, '');
// Paragraphs
// Match lines not starting with HTML tags, and wrap them in <p>
// This is a simplified approach for a single-file demo
html = html.split('\n').map(line => {
if (line.trim() !== '' && !line.match(/^<(h|ul|ol|li|pre|blockquote|hr)/)) {
return `<p>${line}</p>`;
}
return line;
}).join('');
return html;
}
// --- Update Function ---
function updatePreview() {
const rawMarkdown = input.value;
const parsedHTML = parseMarkdown(rawMarkdown);
// Apply HTML
output.innerHTML = parsedHTML;
// Highlight Code Blocks
output.querySelectorAll('pre code').forEach((block) => {
hljs.highlightElement(block);
});
// Update Char Count
charCount.textContent = `${rawMarkdown.length} chars`;
}
// --- Theme Handling ---
function toggleTheme() {
const body = document.body;
const currentTheme = body.getAttribute('data-theme');
const icon = themeToggle.querySelector('i');
if (currentTheme === 'dark') {
body.removeAttribute('data-theme');
icon.classList.remove('fa-sun');
icon.classList.add('fa-moon');
localStorage.setItem('theme', 'light');
} else {
body.setAttribute('data-theme', 'dark');
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
localStorage.setItem('theme', 'dark');
}
}
// --- Toast Notification ---
function showToast(message) {
toastMsg.textContent = message;
toast.classList.add('show');
setTimeout(() => {
toast.classList.remove('show');
}, 3000);
}
// --- Event Listeners ---
// Input Listener
input.addEventListener('input', updatePreview);
// Theme Toggle
themeToggle.addEventListener('click', toggleTheme);
// Reset Button
resetBtn.addEventListener('click', () => {
if(confirm("Are you sure you want to reset the content?")) {
input.value = defaultContent;
updatePreview();
showToast("Content reset to default");
}
});
// Download Button
downloadBtn.addEventListener('click', () => {
const blob = new Blob([input.value], { type: 'text/markdown' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'markdown-file.md';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
showToast("Markdown file downloaded!");
});
// Load Saved Theme
window.addEventListener('DOMContentLoaded', () => {
const savedTheme = localStorage.getItem('theme');
const icon = themeToggle.querySelector('i');
if (savedTheme === 'dark') {
document.body.setAttribute('data-theme', 'dark');
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
}
// Initialize
updatePreview();
});
</script>
</body>
</html>