Created
May 26, 2011 13:50
-
-
Save Yoric/993178 to your computer and use it in GitHub Desktop.
wiki.opajs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* {1 Database and database interaction} | |
*/ | |
/** | |
* Contents of the wiki. | |
* | |
* Pages which do not exist have content "This page is empty". | |
* Note: By definition, pages stored in the database are always well-formed. | |
*/ | |
db { | |
Template.default_content /wiki[string] | |
/wiki[_] = Template.text("This page is empty") | |
} | |
/** | |
* Read the content associated to a topic from the database and return the | |
* corresponding source code. | |
* | |
* @param topic A topic (arbitrary string). | |
* @return If a page has been saved in for [topic], the source code for this | |
* page. Otherwise, the source code for the default page. | |
*/ | |
@publish load_source(topic) { Template.to_source(Template.default, /wiki[topic]) } | |
/** | |
* Read the content associated to a topic from the database and return the | |
* corresponding xhtml, ready to insert. | |
* | |
* @param topic A topic (arbitrary string). | |
* @return If a page has been saved in for [topic], the xhtml for this | |
* page. Otherwise, the xhtml for the default page. | |
* | |
* Note: This function does not perform any caching. | |
*/ | |
@publish load_rendered(topic) { Template.to_xhtml( Template.default, /wiki[topic]) } | |
/** | |
* Accept source code, save the corresponding document in the database. | |
* | |
* @param topic A topic (arbitrary string). | |
* @param source Source code to store at this topic. If this source code | |
* is syntactically valid, store the template datastructure | |
* corresponding to its content [Template.content]. | |
* Otherwise, the source code is implicitly replaced by the document | |
* representing this raw code and this document is saved in the database. | |
* | |
* @return In case of success, the xhtml for the page that has just been | |
* saved. In case of failure, an error message. | |
*/ | |
@publish save_source(topic, source) { | |
match (Template.try_parse(Template.default, source)) { | |
case ~{success} => | |
/wiki[topic] <- success; | |
Template.to_xhtml(Template.default, success) | |
case {failure: *} => | |
/wiki[topic] <- Template.text(source); | |
<>Error: {source}</> | |
} | |
} | |
/** | |
* {1 User interface} | |
*/ | |
/** | |
* Set the user interface in edition mode. | |
* | |
* Load the source code for a topic, display an editable zone for this source code. | |
* | |
* @param topic The topic to edit. | |
*/ | |
edit(topic) { | |
Dom.set_value(#edit_content, load_source(topic)); | |
Dom.hide(#show_content); | |
Dom.show(#edit_content); | |
Dom.give_focus(#edit_content); | |
void | |
} | |
/** | |
* Set the user interface in reading mode. | |
* | |
* Save the source code for a topic (extracted from [#edit_content]), | |
* display the rendered version. | |
* | |
* @param topic The topic to save. | |
*/ | |
save(topic) { | |
content = save_source(topic, Dom.get_value(#edit_content)); | |
Dom.transform([#show_content <- content]); | |
Dom.hide(#edit_content); | |
Dom.show(#show_content); | |
void | |
} | |
/** | |
* Main user interface | |
* | |
* @param topic The topic being consulted | |
* @retrn A resource, ready to be passed to a dispatcher. | |
*/ | |
display(topic) { | |
Resource.styled_page("About {topic}", ["/resources/css.css"], | |
<div id=#header><div id=#logo></div>About {topic}</div> | |
<div class="show_content" id=#show_content ondblclick={_ -> edit(topic)}>{load_rendered(topic)}</> | |
<textarea class="edit_content" id=#edit_content style="display:none" cols="40" rows="30" onblur={_ -> save(topic)}></> | |
) | |
} | |
/** | |
* {1 Main application} | |
*/ | |
/** | |
* Dispatch requests to the user interface | |
* | |
* Note: The empty request is dispatched as if it were "Hello". | |
*/ | |
start(x) { | |
match(x) { | |
case {path: [], ... } => display("Hello"); | |
case {~path, ...} => display(String.capitalize(String.to_lower(List.to_string_using("", "", "::", path)))); | |
} | |
} | |
/** | |
* Statically embed a bundle of resources | |
*/ | |
start_server(Server.of_bundle([@static_include_directory("resources")])); | |
/** | |
* Launch the [start] dispatcher | |
*/ | |
start_server(Server.simple_dispatch(start)); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment