parent
5acd3b362e
commit
aaa15ce893
2 changed files with 239 additions and 0 deletions
@ -0,0 +1,35 @@ |
|||||||
|
<?php declare(strict_types=1); |
||||||
|
|
||||||
|
require __DIR__."/../vendor/autoload.php"; |
||||||
|
|
||||||
|
$source = file_get_contents("php://input"); |
||||||
|
|
||||||
|
try { |
||||||
|
$Instance = new parkdown\Parkdown($source, true); |
||||||
|
echo $Instance->html(); |
||||||
|
} catch (parkdown\ParserError $error) { |
||||||
|
echo "<pre>"; |
||||||
|
|
||||||
|
$message = explode(" ", $error->getMessage()); |
||||||
|
$location = array_shift($message); |
||||||
|
$loc = explode(":", $location); |
||||||
|
$file = array_shift($loc); |
||||||
|
$line = substr(implode(":", $loc), 0, -1); |
||||||
|
[$row, $col] = explode(":", $line); |
||||||
|
|
||||||
|
echo "<a class='error' href=\"javascript: highlight($col, $row);\">$location</a> ".implode(" ", $message); |
||||||
|
|
||||||
|
|
||||||
|
$stackTrace = explode("\n", $error->getTraceAsString()); |
||||||
|
|
||||||
|
echo "<p><small>"; |
||||||
|
foreach ($stackTrace as $step) { |
||||||
|
$step = explode(" ", $step); |
||||||
|
array_shift($step); |
||||||
|
$location = array_shift($step); |
||||||
|
$location = preg_replace("/\(([0-9]+)\):/", ":\$1:", $location); |
||||||
|
|
||||||
|
echo "<a class='error' href='vscode://file/".substr($location, 0, -1)."'>$location</a> ".implode(" ", $step)."<br>"; |
||||||
|
} |
||||||
|
echo "</small></p>"; |
||||||
|
} |
@ -0,0 +1,204 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||||
|
<title>parkdown playground</title> |
||||||
|
<script type="module"> |
||||||
|
const $ = selector => { |
||||||
|
const elements = document.querySelectorAll(selector); |
||||||
|
|
||||||
|
return elements.length < 2 ? elements[0] : elements; |
||||||
|
}; |
||||||
|
|
||||||
|
const output = $("#output"); |
||||||
|
const input = $("#input"); |
||||||
|
const numbers = $(".linenumbers"); |
||||||
|
let timeout; |
||||||
|
|
||||||
|
const updateOutput = (event) => { |
||||||
|
const text = event ? event.target.value : input.value; |
||||||
|
const lines = text.split("\n").length; |
||||||
|
let html = ""; |
||||||
|
for (let i = 1; i <= lines; i++) { |
||||||
|
html += `${i}<br>`; |
||||||
|
} |
||||||
|
numbers.innerHTML = html; |
||||||
|
|
||||||
|
timeout = setTimeout(() => { |
||||||
|
|
||||||
|
fetch("ajax.php", { |
||||||
|
method : "POST", |
||||||
|
headers: { |
||||||
|
"Content-Type" : "application/json" |
||||||
|
}, |
||||||
|
body : text |
||||||
|
}).then(response => response.text()).then(text => output.innerHTML = text); |
||||||
|
}, 1000); |
||||||
|
} |
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => { |
||||||
|
updateOutput(); |
||||||
|
|
||||||
|
input.addEventListener("keydown", event => { |
||||||
|
if (event.key !== "Tab") |
||||||
|
return; |
||||||
|
event.preventDefault(); |
||||||
|
const start = input.selectionStart; |
||||||
|
const end = input.selectionEnd; |
||||||
|
const value = input.value; |
||||||
|
|
||||||
|
input.value = value.substring(0, start) + "\t" + value.substring(end); |
||||||
|
input.selectionStart = input.selectionEnd = (start + 1); |
||||||
|
}); |
||||||
|
|
||||||
|
input.addEventListener("input", event => { |
||||||
|
clearTimeout(timeout); |
||||||
|
updateOutput(event); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
window.highlight = (col, row) => { |
||||||
|
const lines = input.value.split("\n"); |
||||||
|
|
||||||
|
let start = 0; |
||||||
|
let end = 0; |
||||||
|
let i = 0; |
||||||
|
|
||||||
|
for (const line of lines) { |
||||||
|
if (++i === row) { |
||||||
|
end = start + line.length; |
||||||
|
break; |
||||||
|
} |
||||||
|
start += line.length + 1; |
||||||
|
} |
||||||
|
|
||||||
|
start = start + col - 1 === end ? start : start + col; |
||||||
|
|
||||||
|
input.focus(); |
||||||
|
input.setSelectionRange(start, end); |
||||||
|
const lineHeight = input.clientHeight / lines.length; |
||||||
|
$(".editor").scrollTop = lineHeight * (row - 10); |
||||||
|
input.scrollLeft = 0; |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style rel="stylesheet"> |
||||||
|
* { |
||||||
|
box-sizing: border-box; |
||||||
|
outline: 0 !important; |
||||||
|
} |
||||||
|
|
||||||
|
a { |
||||||
|
color: dodgerblue; |
||||||
|
text-decoration: none; |
||||||
|
} |
||||||
|
a:hover { |
||||||
|
text-decoration: underline; |
||||||
|
} |
||||||
|
a.error { |
||||||
|
color: palevioletred; |
||||||
|
} |
||||||
|
|
||||||
|
body { |
||||||
|
display: grid; |
||||||
|
grid-template-columns: 1fr 1fr; |
||||||
|
font-family: sans-serif; |
||||||
|
margin: 0; |
||||||
|
padding: 0; |
||||||
|
height: 100vh; |
||||||
|
overflow: hidden; |
||||||
|
background: #333; |
||||||
|
color: #eee; |
||||||
|
} |
||||||
|
|
||||||
|
body > * { |
||||||
|
width: 100%; |
||||||
|
border: solid 1px #111; |
||||||
|
padding: 0; |
||||||
|
margin: 0; |
||||||
|
} |
||||||
|
|
||||||
|
textarea { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
font-family: monospace; |
||||||
|
box-sizing: content-box; |
||||||
|
background: transparent; |
||||||
|
tab-size: 4; |
||||||
|
border: none; |
||||||
|
padding-bottom: 4rem; |
||||||
|
font-size: 1.2rem; |
||||||
|
overflow-y: clip; |
||||||
|
overflow-x: scroll; |
||||||
|
white-space: nowrap; |
||||||
|
resize: none; |
||||||
|
margin: 1rem 0; |
||||||
|
color: #FAF08B; |
||||||
|
} |
||||||
|
textarea::selection { |
||||||
|
background-color: dodgerblue; |
||||||
|
color: white; |
||||||
|
} |
||||||
|
|
||||||
|
.editor { |
||||||
|
display: grid; |
||||||
|
grid-template-columns: 80px auto; |
||||||
|
gap: 2rem; |
||||||
|
height: 100%; |
||||||
|
border-right: none; |
||||||
|
overflow-y: auto; |
||||||
|
overflow-x: hidden; |
||||||
|
} |
||||||
|
|
||||||
|
.linenumbers { |
||||||
|
font-size: 1.2rem; |
||||||
|
text-align: right; |
||||||
|
padding: 1rem; |
||||||
|
color: #aaa; |
||||||
|
font-family: monospace; |
||||||
|
background: #222; |
||||||
|
} |
||||||
|
|
||||||
|
#output { |
||||||
|
overflow-y: auto; |
||||||
|
padding: 4rem; |
||||||
|
} |
||||||
|
|
||||||
|
::-webkit-scrollbar { |
||||||
|
background-color: transparent; |
||||||
|
width: 16px; |
||||||
|
} |
||||||
|
::-webkit-scrollbar-track { |
||||||
|
background-color: transparent; |
||||||
|
} |
||||||
|
::-webkit-scrollbar-thumb { |
||||||
|
background-color: rgba(255,255,255,0.1); |
||||||
|
border-radius: 16px; |
||||||
|
border: 4px solid #333; |
||||||
|
} |
||||||
|
::-webkit-scrollbar-button { |
||||||
|
display:none; |
||||||
|
} |
||||||
|
</style> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
|
||||||
|
<section class="editor"> |
||||||
|
<section class="linenumbers">1</section> |
||||||
|
<textarea id="input"> |
||||||
|
# parkdown playground |
||||||
|
|
||||||
|
 |
||||||
|
|
||||||
|
* use markdown in the editor |
||||||
|
* view result over there |
||||||
|
|
||||||
|
View parkdown code [here][code]. |
||||||
|
|
||||||
|
[code]: https://git.mike-ochmann.de/MassiveDynamic/Parkdown |
||||||
|
</textarea> |
||||||
|
</section> |
||||||
|
<section id="output"></section> |
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
Loading…
Reference in new issue