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>