|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>MarkView - Markdown Preview</title> |
|
<style> |
|
|
|
body { |
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; |
|
margin: 0; |
|
padding: 0; |
|
background-color: #000; |
|
color: #eaeaea; |
|
} |
|
|
|
|
|
.container { |
|
max-width: 800px; |
|
margin: 0 auto; |
|
padding: 20px; |
|
} |
|
|
|
|
|
.header { |
|
display: flex; |
|
align-items: center; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.logo { |
|
font-size: 24px; |
|
font-weight: bold; |
|
color: #fff; |
|
margin-right: 10px; |
|
} |
|
|
|
.logo span { |
|
color: #0070f3; |
|
} |
|
|
|
|
|
.command-dropdown { |
|
margin-bottom: 20px; |
|
} |
|
|
|
.command-dropdown select { |
|
width: 100%; |
|
padding: 10px; |
|
border: 1px solid #333; |
|
border-radius: 4px; |
|
background-color: #000; |
|
color: #eaeaea; |
|
font-family: 'Inter', sans-serif; |
|
font-size: 14px; |
|
outline: none; |
|
cursor: pointer; |
|
} |
|
|
|
.command-dropdown select:focus { |
|
border-color: #0070f3; |
|
box-shadow: 0 0 0 2px rgba(0, 112, 243, 0.1); |
|
} |
|
|
|
|
|
.modal { |
|
display: none; |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100%; |
|
background-color: rgba(0, 0, 0, 0.8); |
|
justify-content: center; |
|
align-items: center; |
|
z-index: 1000; |
|
} |
|
|
|
.modal-content { |
|
background-color: #111; |
|
padding: 20px; |
|
border-radius: 8px; |
|
width: 400px; |
|
max-width: 90%; |
|
} |
|
|
|
.modal-content h2 { |
|
margin-top: 0; |
|
color: #fff; |
|
} |
|
|
|
.modal-content label { |
|
display: block; |
|
margin-bottom: 10px; |
|
color: #eaeaea; |
|
} |
|
|
|
.modal-content input, |
|
.modal-content select, |
|
.modal-content textarea { |
|
width: 100%; |
|
padding: 10px; |
|
border: 1px solid #333; |
|
border-radius: 4px; |
|
background-color: #000; |
|
color: #eaeaea; |
|
font-family: 'Inter', sans-serif; |
|
font-size: 14px; |
|
outline: none; |
|
margin-bottom: 20px; |
|
} |
|
|
|
.modal-content button { |
|
padding: 10px 20px; |
|
border: none; |
|
border-radius: 4px; |
|
background-color: #0070f3; |
|
color: #fff; |
|
font-family: 'Inter', sans-serif; |
|
font-size: 14px; |
|
cursor: pointer; |
|
} |
|
|
|
.modal-content button:hover { |
|
background-color: #005bb5; |
|
} |
|
|
|
|
|
.editor, .preview { |
|
background-color: #111; |
|
border-radius: 8px; |
|
padding: 20px; |
|
margin-bottom: 20px; |
|
} |
|
|
|
textarea { |
|
width: 100%; |
|
height: 200px; |
|
padding: 10px; |
|
border: 1px solid #333; |
|
border-radius: 4px; |
|
font-family: 'JetBrains Mono', monospace; |
|
font-size: 14px; |
|
background-color: #000; |
|
color: #eaeaea; |
|
resize: vertical; |
|
outline: none; |
|
} |
|
|
|
textarea:focus { |
|
border-color: #0070f3; |
|
box-shadow: 0 0 0 2px rgba(0, 112, 243, 0.1); |
|
} |
|
|
|
|
|
.preview { |
|
color: #eaeaea; |
|
} |
|
|
|
.preview h1, .preview h2, .preview h3 { |
|
margin-top: 0; |
|
color: #fff; |
|
} |
|
|
|
.preview code { |
|
background-color: #333; |
|
padding: 2px 4px; |
|
border-radius: 4px; |
|
font-family: 'JetBrains Mono', monospace; |
|
color: #eaeaea; |
|
} |
|
|
|
.preview pre { |
|
background-color: #333; |
|
padding: 10px; |
|
border-radius: 4px; |
|
overflow-x: auto; |
|
} |
|
|
|
.preview blockquote { |
|
border-left: 4px solid #0070f3; |
|
padding-left: 10px; |
|
color: #999; |
|
margin: 0; |
|
} |
|
|
|
.preview a { |
|
color: #0070f3; |
|
text-decoration: none; |
|
} |
|
|
|
.preview a:hover { |
|
text-decoration: underline; |
|
} |
|
|
|
|
|
.preview img { |
|
margin: 5px; |
|
} |
|
</style> |
|
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet"> |
|
|
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> |
|
</head> |
|
<body> |
|
|
|
<div class="container"> |
|
|
|
<div class="header"> |
|
<div class="logo"> |
|
Mark<span>View</span> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="command-dropdown"> |
|
<select id="command-select"> |
|
<option value="">Select a command...</option> |
|
<option value="/badge">Create a Badge</option> |
|
<option value="/links">Links and Media</option> |
|
<option value="/blocks">Blocks</option> |
|
<option value="/lists">Lists</option> |
|
<option value="/headings">Headings</option> |
|
<option value="/text">Text Formatting</option> |
|
<option value="/tables">Tables</option> |
|
<option value="/tasks">Task Lists</option> |
|
<option value="/hr">Horizontal Rule</option> |
|
<option value="/emoji">Emojis</option> |
|
<option value="/mention">Mentions</option> |
|
</select> |
|
</div> |
|
|
|
|
|
<div class="editor"> |
|
<textarea id="markdown-input" placeholder="Write your Markdown here..."># Welcome to MarkView |
|
**Markdown Preview** with a *dark theme*. |
|
|
|
- List item 1 |
|
- List item 2 |
|
|
|
`Inline code` |
|
|
|
```javascript |
|
function hello() { |
|
console.log('Hello, MarkView!'); |
|
} |
|
```</textarea> |
|
</div> |
|
|
|
|
|
<div class="preview" id="markdown-preview"> |
|
|
|
</div> |
|
</div> |
|
|
|
|
|
|
|
<div class="modal" id="badge-modal"> |
|
<div class="modal-content"> |
|
<h2>Create a Badge</h2> |
|
<label for="badge-label">Label:</label> |
|
<input type="text" id="badge-label" placeholder="e.g., version"> |
|
<label for="badge-message">Message:</label> |
|
<input type="text" id="badge-message" placeholder="e.g., v1.0"> |
|
<label for="badge-color">Color:</label> |
|
<input type="text" id="badge-color" placeholder="e.g., blue"> |
|
<label for="badge-icon">Icon:</label> |
|
<select id="badge-icon"> |
|
<option value="">No Icon</option> |
|
<option value="github">GitHub</option> |
|
<option value="npm">npm</option> |
|
<option value="docker">Docker</option> |
|
<option value="python">Python</option> |
|
<option value="javascript">JavaScript</option> |
|
<option value="react">React</option> |
|
<option value="vue">Vue</option> |
|
<option value="angular">Angular</option> |
|
<option value="apple">Apple</option> |
|
<option value="windows">Windows</option> |
|
<option value="v0">v0</option> |
|
<option value="huggingface">huggingface</option> |
|
<option value="replicate">replicate</option> |
|
<option value="vercel">vercel</option> |
|
<option value="fal">fal</option> |
|
<option value="google">google</option> |
|
<option value="claude">claude</option> |
|
<option value="gemini">gemini</option> |
|
<option value="qwen">qwen</option> |
|
<option value="deepseek">deepseek</option> |
|
</select> |
|
|
|
<label for="badge-url">Link URL (optional):</label> |
|
<input type="text" id="badge-url" placeholder="e.g., https://example.com"> |
|
<button id="insert-badge">Insert Badge</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="modal" id="links-modal"> |
|
<div class="modal-content"> |
|
<h2>Links and Media</h2> |
|
<label for="link-text">Link Text:</label> |
|
<input type="text" id="link-text" placeholder="e.g., Google"> |
|
<label for="link-url">URL:</label> |
|
<input type="text" id="link-url" placeholder="e.g., https://google.com"> |
|
<label for="image-url">Image URL:</label> |
|
<input type="text" id="image-url" placeholder="e.g., https://example.com/image.png"> |
|
<button id="insert-link">Insert Link</button> |
|
<button id="insert-image">Insert Image</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="modal" id="blocks-modal"> |
|
<div class="modal-content"> |
|
<h2>Blocks</h2> |
|
<label for="block-type">Block Type:</label> |
|
<select id="block-type"> |
|
<option value="code">Code Block</option> |
|
<option value="quote">Blockquote</option> |
|
</select> |
|
<label for="block-content">Content:</label> |
|
<textarea id="block-content" placeholder="Enter your content..."></textarea> |
|
<button id="insert-block">Insert Block</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="modal" id="lists-modal"> |
|
<div class="modal-content"> |
|
<h2>Lists</h2> |
|
<label for="list-type">List Type:</label> |
|
<select id="list-type"> |
|
<option value="unordered">Unordered List</option> |
|
<option value="ordered">Ordered List</option> |
|
</select> |
|
<label for="list-items">Items (one per line):</label> |
|
<textarea id="list-items" placeholder="Enter items..."></textarea> |
|
<button id="insert-list">Insert List</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="modal" id="headings-modal"> |
|
<div class="modal-content"> |
|
<h2>Headings</h2> |
|
<label for="heading-level">Heading Level:</label> |
|
<select id="heading-level"> |
|
<option value="1">Heading 1 (#)</option> |
|
<option value="2">Heading 2 (##)</option> |
|
<option value="3">Heading 3 (###)</option> |
|
<option value="4">Heading 4 (####)</option> |
|
<option value="5">Heading 5 (#####)</option> |
|
<option value="6">Heading 6 (######)</option> |
|
</select> |
|
<label for="heading-text">Text:</label> |
|
<input type="text" id="heading-text" placeholder="e.g., My Heading"> |
|
<button id="insert-heading">Insert Heading</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="modal" id="text-modal"> |
|
<div class="modal-content"> |
|
<h2>Text Formatting</h2> |
|
<label for="text-content">Text:</label> |
|
<input type="text" id="text-content" placeholder="e.g., Hello, World!"> |
|
<label for="text-format">Format:</label> |
|
<select id="text-format"> |
|
<option value="bold">Bold (**)</option> |
|
<option value="italic">Italic (*)</option> |
|
<option value="strikethrough">Strikethrough (~~)</option> |
|
<option value="inline-code">Inline Code (`)</option> |
|
</select> |
|
<button id="insert-text">Insert Text</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="modal" id="tables-modal"> |
|
<div class="modal-content"> |
|
<h2>Tables</h2> |
|
<label for="table-headers">Headers (comma-separated):</label> |
|
<input type="text" id="table-headers" placeholder="e.g., Name, Age, City"> |
|
<label for="table-rows">Rows (one per line, comma-separated):</label> |
|
<textarea id="table-rows" placeholder="e.g., John, 25, New York"></textarea> |
|
<button id="insert-table">Insert Table</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="modal" id="tasks-modal"> |
|
<div class="modal-content"> |
|
<h2>Task Lists</h2> |
|
<label for="task-items">Tasks (one per line):</label> |
|
<textarea id="task-items" placeholder="e.g., [x] Task 1"></textarea> |
|
<button id="insert-tasks">Insert Tasks</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="modal" id="hr-modal"> |
|
<div class="modal-content"> |
|
<h2>Horizontal Rule</h2> |
|
<p>Insert a horizontal rule:</p> |
|
<button id="insert-hr">Insert Horizontal Rule</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="modal" id="emoji-modal"> |
|
<div class="modal-content"> |
|
<h2>Emojis</h2> |
|
<label for="emoji">Select an Emoji:</label> |
|
<select id="emoji"> |
|
<option value="π">π Grinning Face</option> |
|
<option value="π">π Rocket</option> |
|
<option value="β€οΈ">β€οΈ Heart</option> |
|
<option value="π">π Star</option> |
|
<option value="π₯">π₯ Fire</option> |
|
</select> |
|
<button id="insert-emoji">Insert Emoji</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<div class="modal" id="mention-modal"> |
|
<div class="modal-content"> |
|
<h2>Mentions</h2> |
|
<label for="mention-username">Username:</label> |
|
<input type="text" id="mention-username" placeholder="e.g., octocat"> |
|
<button id="insert-mention">Insert Mention</button> |
|
</div> |
|
</div> |
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> |
|
<script> |
|
const input = document.getElementById('markdown-input'); |
|
const preview = document.getElementById('markdown-preview'); |
|
const commandSelect = document.getElementById('command-select'); |
|
|
|
|
|
function updatePreview() { |
|
const markdownText = input.value; |
|
preview.innerHTML = marked.parse(markdownText); |
|
} |
|
|
|
|
|
function showModal(modalId) { |
|
const modal = document.getElementById(modalId); |
|
modal.style.display = 'flex'; |
|
} |
|
|
|
|
|
function hideModal(modalId) { |
|
const modal = document.getElementById(modalId); |
|
modal.style.display = 'none'; |
|
} |
|
|
|
|
|
function insertBadge() { |
|
const label = document.getElementById('badge-label').value || 'label'; |
|
const message = document.getElementById('badge-message').value || 'message'; |
|
const color = document.getElementById('badge-color').value || 'blue'; |
|
const icon = document.getElementById('badge-icon').value; |
|
const url = document.getElementById('badge-url').value; |
|
|
|
let badgeUrl = `https://img.shields.io/badge/${encodeURIComponent(label)}-${encodeURIComponent(message)}-${color}`; |
|
if (icon) { |
|
badgeUrl += `?logo=${icon}`; |
|
} |
|
|
|
|
|
let badgeMarkdown = ``; |
|
|
|
|
|
if (url) { |
|
badgeMarkdown = `[${badgeMarkdown}](${url})`; |
|
} |
|
|
|
|
|
input.value += `\n${badgeMarkdown}`; |
|
updatePreview(); |
|
hideModal('badge-modal'); |
|
} |
|
|
|
|
|
function insertLink() { |
|
const text = document.getElementById('link-text').value || 'Link'; |
|
const url = document.getElementById('link-url').value || '#'; |
|
const linkMarkdown = `[${text}](${url})`; |
|
|
|
input.value += `\n${linkMarkdown}`; |
|
updatePreview(); |
|
hideModal('links-modal'); |
|
} |
|
|
|
|
|
function insertImage() { |
|
const url = document.getElementById('image-url').value || '#'; |
|
const imageMarkdown = ``; |
|
|
|
input.value += `\n${imageMarkdown}`; |
|
updatePreview(); |
|
hideModal('links-modal'); |
|
} |
|
|
|
|
|
function insertBlock() { |
|
const type = document.getElementById('block-type').value; |
|
const content = document.getElementById('block-content').value; |
|
|
|
let blockMarkdown = ''; |
|
if (type === 'code') { |
|
blockMarkdown = `\`\`\`\n${content}\n\`\`\``; |
|
} else if (type === 'quote') { |
|
blockMarkdown = `> ${content}`; |
|
} |
|
|
|
input.value += `\n${blockMarkdown}`; |
|
updatePreview(); |
|
hideModal('blocks-modal'); |
|
} |
|
|
|
|
|
function insertList() { |
|
const type = document.getElementById('list-type').value; |
|
const items = document.getElementById('list-items').value.split('\n').filter(item => item.trim() !== ''); |
|
|
|
let listMarkdown = ''; |
|
if (type === 'unordered') { |
|
listMarkdown = items.map(item => `- ${item}`).join('\n'); |
|
} else if (type === 'ordered') { |
|
listMarkdown = items.map((item, index) => `${index + 1}. ${item}`).join('\n'); |
|
} |
|
|
|
input.value += `\n${listMarkdown}`; |
|
updatePreview(); |
|
hideModal('lists-modal'); |
|
} |
|
|
|
|
|
function insertHeading() { |
|
const level = document.getElementById('heading-level').value; |
|
const text = document.getElementById('heading-text').value || 'Heading'; |
|
|
|
const headingMarkdown = `${'#'.repeat(level)} ${text}`; |
|
|
|
input.value += `\n${headingMarkdown}`; |
|
updatePreview(); |
|
hideModal('headings-modal'); |
|
} |
|
|
|
|
|
function insertText() { |
|
const content = document.getElementById('text-content').value || 'Text'; |
|
const format = document.getElementById('text-format').value; |
|
|
|
let formattedText = ''; |
|
if (format === 'bold') { |
|
formattedText = `**${content}**`; |
|
} else if (format === 'italic') { |
|
formattedText = `*${content}*`; |
|
} else if (format === 'strikethrough') { |
|
formattedText = `~~${content}~~`; |
|
} else if (format === 'inline-code') { |
|
formattedText = `\`${content}\``; |
|
} |
|
|
|
input.value += `\n${formattedText}`; |
|
updatePreview(); |
|
hideModal('text-modal'); |
|
} |
|
|
|
|
|
function insertTable() { |
|
const headers = document.getElementById('table-headers').value.split(',').map(header => header.trim()); |
|
const rows = document.getElementById('table-rows').value.split('\n').map(row => row.split(',').map(cell => cell.trim())); |
|
|
|
let tableMarkdown = `| ${headers.join(' | ')} |\n`; |
|
tableMarkdown += `| ${headers.map(() => '---').join(' | ')} |\n`; |
|
rows.forEach(row => { |
|
tableMarkdown += `| ${row.join(' | ')} |\n`; |
|
}); |
|
|
|
input.value += `\n${tableMarkdown}`; |
|
updatePreview(); |
|
hideModal('tables-modal'); |
|
} |
|
|
|
|
|
function insertTasks() { |
|
const tasks = document.getElementById('task-items').value.split('\n').filter(task => task.trim() !== ''); |
|
|
|
const tasksMarkdown = tasks.map(task => `- ${task}`).join('\n'); |
|
|
|
input.value += `\n${tasksMarkdown}`; |
|
updatePreview(); |
|
hideModal('tasks-modal'); |
|
} |
|
|
|
|
|
function insertHR() { |
|
input.value += `\n---\n`; |
|
updatePreview(); |
|
hideModal('hr-modal'); |
|
} |
|
|
|
|
|
function insertEmoji() { |
|
const emoji = document.getElementById('emoji').value; |
|
input.value += `\n${emoji}`; |
|
updatePreview(); |
|
hideModal('emoji-modal'); |
|
} |
|
|
|
|
|
function insertMention() { |
|
const username = document.getElementById('mention-username').value || 'username'; |
|
input.value += `\n@${username}`; |
|
updatePreview(); |
|
hideModal('mention-modal'); |
|
} |
|
|
|
|
|
input.addEventListener('input', updatePreview); |
|
commandSelect.addEventListener('change', (e) => { |
|
const command = e.target.value; |
|
if (command === '/badge') { |
|
showModal('badge-modal'); |
|
} else if (command === '/links') { |
|
showModal('links-modal'); |
|
} else if (command === '/blocks') { |
|
showModal('blocks-modal'); |
|
} else if (command === '/lists') { |
|
showModal('lists-modal'); |
|
} else if (command === '/headings') { |
|
showModal('headings-modal'); |
|
} else if (command === '/text') { |
|
showModal('text-modal'); |
|
} else if (command === '/tables') { |
|
showModal('tables-modal'); |
|
} else if (command === '/tasks') { |
|
showModal('tasks-modal'); |
|
} else if (command === '/hr') { |
|
showModal('hr-modal'); |
|
} else if (command === '/emoji') { |
|
showModal('emoji-modal'); |
|
} else if (command === '/mention') { |
|
showModal('mention-modal'); |
|
} |
|
}); |
|
|
|
|
|
document.getElementById('insert-badge').addEventListener('click', insertBadge); |
|
document.getElementById('insert-link').addEventListener('click', insertLink); |
|
document.getElementById('insert-image').addEventListener('click', insertImage); |
|
document.getElementById('insert-block').addEventListener('click', insertBlock); |
|
document.getElementById('insert-list').addEventListener('click', insertList); |
|
document.getElementById('insert-heading').addEventListener('click', insertHeading); |
|
document.getElementById('insert-text').addEventListener('click', insertText); |
|
document.getElementById('insert-table').addEventListener('click', insertTable); |
|
document.getElementById('insert-tasks').addEventListener('click', insertTasks); |
|
document.getElementById('insert-hr').addEventListener('click', insertHR); |
|
document.getElementById('insert-emoji').addEventListener('click', insertEmoji); |
|
document.getElementById('insert-mention').addEventListener('click', insertMention); |
|
|
|
|
|
window.addEventListener('click', (e) => { |
|
if (e.target.classList.contains('modal')) { |
|
e.target.style.display = 'none'; |
|
} |
|
}); |
|
|
|
|
|
updatePreview(); |
|
</script> |
|
|
|
</body> |
|
</html> |