colorful rat Ratfactor.com > Dave's Repos

htmlwarden

A flat HTML file Wiki in PHP
git clone http://ratfactor.com/repos/htmlwarden/htmlwarden.git

htmlwarden/edit.php

Download raw file: edit.php

1 <?php 2 require 'core.php'; 3 4 require_login(); 5 6 $page_name = $_REQUEST['page']; 7 $fname = "${GLOBALS['page_dir']}/${page_name}.html"; 8 9 if(strlen($page_name) < 1){ 10 echo "Error: No page name specified."; 11 exit; 12 } 13 ?> 14 <!DOCTYPE html> 15 <html lang="<?=$GLOBALS['lang']?>"> 16 <head> 17 <title>Wiki</title> 18 <meta charset="utf-8"> 19 <meta name="viewport" content="width=device-width, initial-scale=1"> 20 <link rel="icon" type="image/png" sizes="32x32" href="icon32x32.png"> 21 <style> 22 body { 23 margin: auto; 24 padding: 20px; 25 max-width: 1400px; 26 font-size: 1.2em; 27 background: #FFE; 28 } 29 .toolbar { 30 width: 100%; 31 text-align: right; 32 } 33 .toolbar button { 34 padding: 4px; 35 margin: 4px; 36 font-size: 18px; 37 height: 30px; 38 min-width: 30px; 39 border: 1px solid #000; 40 border-radius: 3px; 41 } 42 #tool_save { background: #B8FFB8; } 43 #tool_cancel { background: #FFDADA; } 44 45 #editor { 46 display: flex; 47 width: 100%; 48 } 49 #html_view { 50 flex: 1; 51 padding: 5px; 52 border: 4px solid #EEC; 53 max-width: 700px; 54 background: #FFF; 55 } 56 #code_view { 57 flex: 1; 58 background: white; 59 } 60 #code_view form { width: 100%; height: 100%; } 61 #code_view textarea { 62 width: 100%; 63 height: 100%; 64 padding: 10px; 65 box-sizing: border-box; 66 background: #333; 67 color: #fdd; 68 font-size: 1.1em; 69 } 70 iframe.link-creator { 71 width: 100%; 72 border: none; 73 height: 160px; 74 overflow: auto; 75 } 76 .help-table { 77 width: 400px; 78 background: #ffe8ce; 79 border: 1px solid black; 80 border-collapse: collapse; 81 float: right; 82 } 83 .help-table td { border-bottom: 1px solid #b7a591; padding: 5px; } 84 .help_code { font-family: monospace; } 85 </style> 86 </head> 87 <body> 88 89 <div class="toolbar"> 90 <button id="tool_help">Help</button> 91 <button id="tool_link">Insert Link</button> 92 <button id="tool_cancel">Discard Changes</button> 93 <button id="tool_save">Save Changes</button> 94 </div> 95 96 <div id="syntax_help" style="display: none; "> 97 <table inert="inert" class="help-table"> 98 <tr><td class="help_code">= Heading</td> 99 <td style="font-size: 1.3em; font-weight:bold;">Heading</td> 100 </tr> 101 <tr><td class="help_code">== Sub-Heading</td> 102 <td style="font-size: 1.1em; font-weight:bold;">Sub-Heading</td> 103 </tr> 104 <tr><td class="help_code">pagename[]</td> 105 <td><a href="#">pagename</a></td> 106 </tr> 107 <tr><td class="help_code">pagename[Page Name]</td> 108 <td><a href="#">Page Name</a></td> 109 </tr> 110 </table> 111 </div> 112 113 <div id="link_creator" style="display: none;"></div> 114 115 <div id="editor"> 116 <!-- the inert attribute keeps the links from being clickable --> 117 <div id="html_view" inert="inert"><?php 118 if(file_exists($fname)){ 119 include $fname; 120 } 121 else{ 122 echo "<h1>$page_name</h1>\n\n<p>Edit me!</p>"; 123 } 124 ?></div> 125 <div id="code_view"> 126 <textarea name="body"></textarea> 127 </div> 128 </div> 129 <form id="my_form" action="save.php?page=<?=$page_name?>" method="post"> 130 <input id="my_body" type="hidden" name="body"> 131 </form> 132 133 <script> 134 var link_prefix = '<?=$GLOBALS['wiki_link_path']?>'; 135 136 function debounce(ms, callback){ 137 var timer; 138 return function () { 139 clearTimeout(timer); 140 timer = setTimeout(callback, ms); 141 } 142 } 143 144 var html_view = document.getElementById('html_view'); 145 var code_area = document.querySelector('#code_view textarea'); 146 147 148 // Keep the two panes in sync. 149 code_area.addEventListener('input', debounce(500, c2h)); 150 //html_view.addEventListener('input', debounce(500, h2c)); 151 152 // One-time conversion of extremely limited subset of HTML 153 // to a light markup alternative: 154 function h2c(){ 155 var i,j,e,e2,p,href; 156 157 // We *always* start with the title on the first line 158 var title_tag = html_view.querySelector('h1'); 159 var txt = title_tag ? title_tag.textContent : 'Untitled'; 160 if(txt.length < 1){ txt = 'Untitled'; } 161 txt += "\n\n"; 162 163 // old skool 'for' loop required for element collection 164 for(var i=0; i<html_view.children.length; i++){ 165 e = html_view.children[i]; 166 switch(e.nodeName){ 167 case 'H1': continue; // We've already taken care of the title 168 case 'H2': p = '# ' + e.textContent + "\n\n"; break; 169 case 'H3': p = '## ' + e.textContent + "\n\n"; break; 170 case 'img': p = 'img:' + e.getAttribute('src') + "\n"; break; 171 case 'P': 172 p=''; 173 for(j=0; j<e.childNodes.length; j++){ 174 e2 = e.childNodes[j]; 175 if(e2.nodeType === Node.TEXT_NODE){ 176 p += e2.textContent; 177 } 178 179 if(e2.nodeType === Node.ELEMENT_NODE){ 180 if(e2.nodeName === 'A'){ 181 href = e2.getAttribute('href'); 182 if(href.startsWith(link_prefix)){ 183 href = href.replace(link_prefix,""); 184 } 185 p += href + '[' + e2.textContent + ']\n'; 186 } 187 } 188 } 189 p += "\n"; 190 break; 191 default: p = '<html>\n' + e.outerHTML + '\n</html>\n\n'; 192 } 193 txt += p; 194 } 195 196 code_area.value = txt;// + html_view.innerHTML; 197 } 198 199 var rx_h2=/^# (.*)$/; 200 var rx_h3=/^## (.*)$/; 201 var rx_img=/^img:(.*)$/; 202 var rx_a=/^([^[]+)\[(.*)\]/; 203 var rx_html=/^\<html\>$/; 204 var rx_end_html=/^\<\/html\>$/; 205 var rx_blank=/^\s*$/; 206 207 function c2h(){ 208 var line, m, link_title; 209 var lines = code_area.value.split(/\r\n|\r|\n/); 210 var para_open = false; 211 212 // Title always first 213 var title = lines[0]; 214 if(title.length < 1){ title = "Untitled"; } 215 var html = "<h1>" + title + "</h1>\n"; 216 217 for(var i=1; i<lines.length; i++){ 218 line = lines[i]; 219 if(m = rx_h2.exec(line)){ close_p(); html += '<h2>' + m[1] + '</h2>\n'; continue; } 220 if(m = rx_h3.exec(line)){ close_p(); html += '<h3>' + m[1] + '</h3>\n'; continue; } 221 222 if(m = rx_a.exec(line)){ 223 open_p(); 224 link_title = m[2]; 225 if(link_title.length < 1){ 226 link_title = m[1]; 227 } 228 html += '<a href="' + link_prefix + m[1] + '">' + link_title + '</a>'; 229 continue; 230 } 231 if(rx_html.exec(line)){ 232 close_p(); 233 while(i<lines.length && !rx_end_html.exec(line)){ 234 line = lines[i]; 235 i++; 236 html += line + "\n"; 237 } 238 continue; 239 } 240 241 // Blank line ends current p, if we're in one 242 if(rx_blank.test(line)){ 243 close_p(); 244 continue; 245 } 246 247 // Else, we've got paragraph content 248 open_p(); 249 html += line + "\n"; 250 } 251 252 function open_p(){ 253 if(!para_open){ 254 html += "<p>"; 255 para_open = true; 256 } 257 } 258 function close_p(){ 259 if(para_open){ 260 html += "</p>"; 261 para_open = false; 262 263 } 264 } 265 266 close_p(); 267 html_view.innerHTML = html; 268 269 } 270 271 var myform = document.getElementById('my_form'); 272 var mybody = document.getElementById('my_body'); 273 document.getElementById('tool_save').addEventListener('click', function(){ 274 mybody.value = html_view.innerHTML; 275 myform.submit(); 276 }); 277 document.getElementById('tool_cancel').addEventListener('click', function(){ 278 if(confirm("Are you sure?")){ 279 location.assign('index.php?page=<?=$page_name?>'); 280 } 281 }); 282 283 function insertText(text){ 284 console.log("inserting: ",text); 285 var start = code_area.selectionStart; 286 var end = code_area.selectionEnd; 287 code_area.setRangeText(text, start, end, 'end'); 288 c2h(); 289 } 290 291 // The link creator iframe and helper functions 292 var link_creator = document.getElementById('link_creator'); 293 var tool_link = document.getElementById('tool_link'); 294 tool_link.addEventListener('click', function(){ 295 if(link_creator.style.display === "none"){ 296 tool_link.textContent = "Cancel Link"; 297 link_creator.style.display = "initial"; 298 link_creator.innerHTML = 299 '<iframe class="link-creator" src="link_creator.php" title="Link Creator"></iframe>'; 300 } 301 else{ 302 close_link_creator(); 303 } 304 }); 305 306 function close_link_creator(){ 307 tool_link.textContent = "Insert Link"; 308 link_creator.style.display = "none"; 309 } 310 311 function insert_link(url, title){ 312 insertText(url + '[' + title + ']\n'); 313 } 314 315 // The Help button toggles the syntax help box 316 var syntax_help = document.getElementById('syntax_help'); 317 var tool_help = document.getElementById('tool_help'); 318 tool_help.addEventListener('click', function(){ 319 if(syntax_help.style.display === "none"){ 320 tool_help.textContent = "Close Help"; 321 syntax_help.style.display = "initial"; 322 } 323 else{ 324 tool_help.textContent = "Help"; 325 syntax_help.style.display = "none"; 326 } 327 }); 328 329 // Start! Do one-time conversion of HTML to wiki markup 330 h2c(); 331 </script> 332 333 </body> 334 </html>