-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathhello_wiki.opa
146 lines (133 loc) · 3.77 KB
/
hello_wiki.opa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
* {1 Import standard classes of bootstrap css}
*
* see http://twitter.github.com/bootstrap/
*/
import stdlib.themes.bootstrap
/**
* {1 Import markdown syntax}
*/
import stdlib.tools.markdown
/**
* {1 Database and database interaction}
*/
/**
* Contents of the wiki.
*
* Pages which do not exist have content "This page is empty".
*/
database stringmap(string) /wiki
database /wiki[_] = "This page is empty. Double-click to edit."
/**
* Read the content associated to a topic from the database and return the
* corresponding Markdown source.
*
* @param topic A topic (arbitrary string).
* @return If a page has been saved in for [topic], the source for this
* page. Otherwise, the source for the default page.
*/
function load_source(topic) {
/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.
* Note: This function is exposed because a user can ask the rendered content for any topic.
*/
exposed function load_rendered(topic) {
source = load_source(topic);
Markdown.xhtml_of_string(Markdown.default_options, source);
}
/**
* Accept source and save the corresponding document in the database.
*
* @param topic A topic (arbitrary string).
* @param source Markdown source to store at this topic.
* @return The xhtml for the page that has just been saved.
*
* Note: This function is exposed because a user can save any content for any topic.
*/
exposed function save_source(topic, source) {
/wiki[topic] <- source;
load_rendered(topic);
}
/**
* {1 User interface}
*/
/**
* Set the user interface in edition mode.
*
* Load the Markdown source for a topic, display an editable zone
* for this markdown.
*
* @param topic The topic to edit.
*/
function edit(topic) {
Dom.set_value(#edit_content, load_source(topic));
Dom.hide(#show_content);
Dom.show(#edit_content);
Dom.give_focus(#edit_content);
}
/**
* Set the user interface in reading mode.
*
* Save the Markdown source for a topic (extracted from [#edit_content]),
* display the rendered version.
*
* @param topic The topic to save.
*/
function save(topic) {
content = save_source(topic, Dom.get_value(#edit_content));
#show_content = content;
Dom.hide(#edit_content);
Dom.show(#show_content);
}
/**
* Main user interface
*
* @param topic The topic being consulted
* @return A resource, ready to be passed to a dispatcher.
*/
function display(topic) {
xhtml =
<div class="navbar navbar-fixed-top"><div class="navbar-inner"><div class="container"><div id=#logo></div></div></div></div>
<div class="content container">
<div class="page-header"><h1>About {topic}</h1></div>
<div class="well" id=#show_content ondblclick={function(_) { edit(topic) }}>{load_rendered(topic)}</div>
<textarea rows="30" id=#edit_content onblur={function(_) { save(topic) }}></textarea>
</div>;
Resource.styled_page("About {topic}", ["/resources/css.css"], xhtml);
}
/**
* {1 Main application}
*/
/**
* Dispatch requests to the user interface
*
* Note: The empty request is dispatched as if it were "Hello".
*/
function start(url) {
match (url) {
case {path:[] ... } :
display("Hello");
case {~path ...} :
display(String.capitalize(String.to_lower(String.concat("::", path))));
}
}
/**
* Start the wiki server
*/
Server.start(
Server.http,
/** Statically embed a bundle of resources */
[ {resources: @static_include_directory("resources")}
/** Launch the [start] dispatcher */
, {dispatch: start}
]
);