Skip to content

Instantly share code, notes, and snippets.

@Yoric
Created May 26, 2011 14:37
Show Gist options
  • Save Yoric/993275 to your computer and use it in GitHub Desktop.
Save Yoric/993275 to your computer and use it in GitHub Desktop.
wiki.opapy
##
# {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 /wiki as Template.default_content[string]
db /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 def 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 def 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 def save_source(topic, source):
match Template.try_parse(Template.default, source):
~{success}:
/wiki[topic] <- success
Template.to_xhtml(Template.default, success)
{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.
#
def 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.
#
def 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.
#
def 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={lambda *: edit(topic)}>{load_rendered(topic)}</>
<textarea class="edit_content" id=$edit_content style="display:none" cols="40" rows="30" onblur={lambda *: save(topic)}></>
)
##
# {1 Main application}
#
##
# Dispatch requests to the user interface
#
# Note: The empty request is dispatched as if it were "Hello".
#
def start(x):
match(x):
{path: [], ... }: display("Hello")
{~path, ...}: display(String.capitalize(String.to_lower(List.to_string_using("", "", "::", path))))
##
# Statically embed a bundle of resources
#
server = Server.of_bundle([@static_include_directory("resources")])
##
# Launch the [start] dispatcher
#
server = Server.simple_dispatch(start)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment