The idea here is to make the minimum viable AJAX backend. Rather than via the URI, the page is requested via a JSON message. So we need to take JSON via POST, and decode it, find the file
Backend
<?php
require_once("Parsedown.php");
define('PageNotFound','PageNotFound'); # page to return if the page does not exist
define('PagesDir','pages');
define('PageExt','ptmd');
if( $_SERVER['REQUEST_METHOD'] !== "POST" ) {
echo '{ "error": "Must POST", "source": "", "path": "" }';
exit;
}
function the_json() {
global $input;
$input = file_get_contents('php://input');
return $input;
}
function the_data() {
global $json;
$json = the_json();
return json_decode(the_json(),true);
}
function fpath_for_path($path) {
return PagesDir."/".$path.".".PageExt;
}
function send_as_json($data) {
echo json_encode($data);
exit;
}
$data = the_data();
if( !isset($data['path']) ) {
$path = PageNotFound;
} else {
$path = $data['path'];
if( !file_exists(fpath_for_path($path)) ) {
$path = PageNotFound;
}
}
$fpath = fpath_for_path($path);
$source = file_get_contents($fpath);
$reply = [
"path" => $path,
"source" => $source,
"input" => $data,
"json" => $json
];
$ptmd = new Parsedown();
$pinput = preg_replace('/\[\[([^\]]+)\]\]/','[\1](\1)',$source);
$reply["pinput"] = $pinput;
$html = $ptmd->text($pinput);
$reply["html"] = $html;
$reply["nhtml"] = "";
send_as_json($reply);
Frontend
app.js
class Ajax {
constructor(backend) {
this.backend = backend
}
getPage(path,callback) {
const request = { path }
return this.dispatch(request,callback)
}
putPage(path,source,callback) {
const request = { "type": "put", path, source }
return this.dispatch(request,callback)
}
dispatch(request,callback) {
console.log(request)
$.ajax({
type: "POST",
data: JSON.stringify(request),
url: this.backend,
success: callback,
dataType: "json"
}).fail(error => {
const { responseText } = error
console.log({responseText,error})
const errorData = {
pagename: "ERROR",
navbar: `Failed to load page ${url}`,
tags: [],
body: responseText.replace(/&/g,"&").replace(/>/g,">").replace(/</g,"<")
}
window.error = error
window.responseText = responseText
window.errorData = errorData
})
}
}
class ViewBase {
constructor() {
this.data = null
console.log(10)
}
setData(data) {
this.data = data
}
render() {
if( !this.data ) return
}
}
class ViewHtml extends ViewBase {
constructor(target) {
super()
this.target = target
}
render() {
this.target.innerHTML = this.data.html
}
}
class ViewSource extends ViewBase {
constructor(target) {
super()
this.target = target
}
render() {
this.target.innerText = this.data.source
}
}
class EditSource extends ViewBase {
constructor(target) {
super()
this.target = target
this.textarea = target.querySelector("textarea")
}
render() {
this.textarea.value = this.data.source
}
}
export { Ajax, ViewBase, ViewSource, ViewHtml, EditSource }
the rest
Note that we use JQuery to handle the Ajax requests.
<script>
window.q = (x,y=document) => y.querySelector(x)
window.qq = (x,y=document) => Array.from(y.querySelectorAll(x))
</script>
<script type="module">
import { Ajax, ViewHtml, ViewSource, EditSource } from './app.js'
const ajax = new Ajax("http://t420b/a/backend.php")
console.log(1)
window.addEventListener("load", _ => {
console.log(2)
const viewhtml = document.createElement("div")
viewhtml.classList.add("view")
viewhtml.classList.add("view-html")
const viewsource = document.createElement("div")
viewsource.classList.add("view")
viewsource.classList.add("view-source")
const editsource = document.createElement("div")
editsource.classList.add("view")
editsource.classList.add("edit-source")
const textarea = document.createElement("textarea")
editsource.append(textarea)
const body = document.body
body.append(viewhtml)
body.append(viewsource)
body.append(editsource)
const view_html = new ViewHtml(viewhtml)
const view_source = new ViewSource(viewsource)
const edit_source = new EditSource(editsource)
const success = x => {
console.log("this",x)
view_html.setData(x)
view_source.setData(x)
edit_source.setData(x)
view_html.render()
view_source.render()
edit_source.render()
}
ajax.getPage("0",success)
window.loadPage = x => ajax.getPage(x,success)
})
</script>
<script>
window.addEventListener("load", _ => {
const input = q("input")
input.addEventListener("keydown", e => {
if( e.key == "Enter" ) {
e.preventDefault()
const p = input.value
input.value = ""
input.focus()
return window.loadPage(p)
}
})
input.focus()
})
</script>