<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <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: pre; 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; max-width: 100%; } #output code { word-break: break-word; white-space: break-spaces; } #output img { max-width: 100%; height: auto; } ::-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; } @media (max-width: 920px) { body { grid-template-columns: 1fr !important; grid-template-rows: 1fr 1fr; } textarea, .linenumbers { font-size: 1rem; } textarea { margin: 0.5rem 0; } .linenumbers { padding: 0.5rem; } .editor { grid-template-columns: 50px auto; gap: 1rem; } #output { padding: 1rem; } } </style> </head> <body> <section class="editor"> <section class="linenumbers">1</section> <textarea id="input"> # Parkdown – a simple recursive descent Markdown parser for PHP *(version >= 8.1)*  ## Specification ### Index * [Block types](#supported_block_types) * [Inline types](#supported_inline_types) * [Examples](#examples) * [Paragraphs](#paragraphs) * [Images](#images) * [Horizontal Rules](#horizontal_rules) * [Block quotes](#block_quotes) * [Code blocks](#code_blocks) * [Tables](#tables) * [References](#references) * [Usage](#usage) * [Testing](#testing) ### Supported block types Parkdown currently support the following block types: * codeblocks *(with the ability to specify a language for the code block)* * tables *(with alignment specification)* * paragraphs * block quotes * lists *(like this one)* * also nested * horizontal rules `---` ### Supported inline types Parkdown currently support the following block types: * bold text (`**bold**`) * italic text (`*italic*`) * code snippets * images (``) * links (`[link text][url or reference]`) ### Additional functionality * references (`[marker]: URL`) ## Examples ### Paragraphs ```markdown A simple paragraph can contain **bold text**, `inline codeblocks` and *italic text*. We can also link [with a direct url][https://google.com] *(i.e. to google)* or via reference to [a later defined url][massivedynamic], if we so desire. ``` A simple paragraph can contain **bold text**, `inline codeblocks` and *italic text*. We can also link [with a direct url](https://google.com) *(i.e. to google)* or via reference to [a later defined url][massivedynamic], if we so desire. Paragraphs can be annotated with `id` and `class` attributes: ```markdown Paragraphs can be annotated with ids and classes {.thisIsAClass, .anotherClass, #thisIsAnID} ``` results in Paragraphs can be annotated with ids and classes {.thisIsAClass, .anotherClass, #thisIsAnID} ```html <p class="thisIsAClass anotherClass" id="thisIsAnID"> Paragraphs can be annotated with ids and classes </p> ``` ### Images ```markdown  ```  ### Horizontal rules ```markdown --- ``` --- ### Block quotes ```markdown > Only two things are infinite, > the universe and human stupidity, > i am not totally shure about the universe, though... > – Albert Einstein ``` > Only two things are infinite, > the universe and human stupidity, > i am not totally shure about the universe, though... > – Albert Einstein ### Code blocks ```markdown \`\`\`php function main(int $argc, array $argv) : int { echo "Hello World!"; return 0; } \`\`\` ``` ```php function main(int $argc, array $argv) : int { echo "Hello World!"; return 0; } ``` ### Tables ```markdown | Product name | Amount | Price | |--------------|:--------:|-------:| | Football | 7 | $18,00 | | Golfball | 122 | $7,00 | | Fooseball | 355 | $1,00 | | Puck | 58 | $12,00 | ``` | Product name | Amount | Price | |--------------|:--------:|-------:| | Football | 7 | $18,00 | | Golfball | 122 | $7,00 | | Fooseball | 355 | $1,00 | | Puck | 58 | $12,00 | ### References ```markdown [massivedynamic]: https://massivedynamic.eu ``` [massivedynamic]: https://massivedynamic.eu ## Usage Simply construct an new `parkdown\Parkdown` object and pass the Markdown source code to it's constructor. The parsed `DOMDocument` or it's `HTML` output can then be retrieved through the `::html()` and `::tree()` member functions. **Example** ```php use parkdown\Parkdown; $source = " This is a **bold** word in a paragraph. "; $parser = new Parkdown($source); $tree = $parser->tree(); print_r($tree); echo $parser->html(); ``` ## Testing Unit tests can be run via `composer`: ``` composer test ``` </textarea> </section> <section id="output"></section> </body> </html>