instiki 0.9.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/CHANGELOG +165 -0
  2. data/README +68 -172
  3. data/app/controllers/admin_controller.rb +94 -0
  4. data/app/controllers/application.rb +131 -0
  5. data/app/controllers/file_controller.rb +129 -0
  6. data/app/controllers/wiki_controller.rb +354 -0
  7. data/{libraries/view_helper.rb → app/helpers/application_helper.rb} +68 -33
  8. data/app/models/author.rb +3 -3
  9. data/app/models/chunks/category.rb +33 -31
  10. data/app/models/chunks/chunk.rb +86 -20
  11. data/app/models/chunks/engines.rb +54 -38
  12. data/app/models/chunks/include.rb +41 -29
  13. data/app/models/chunks/literal.rb +31 -19
  14. data/app/models/chunks/nowiki.rb +28 -31
  15. data/app/models/chunks/test.rb +18 -18
  16. data/app/models/chunks/uri.rb +182 -97
  17. data/app/models/chunks/wiki.rb +141 -82
  18. data/app/models/file_yard.rb +58 -0
  19. data/app/models/page.rb +112 -86
  20. data/app/models/page_lock.rb +22 -23
  21. data/app/models/page_set.rb +89 -64
  22. data/app/models/revision.rb +123 -90
  23. data/app/models/web.rb +176 -89
  24. data/app/models/wiki_content.rb +207 -105
  25. data/app/models/wiki_service.rb +233 -83
  26. data/app/models/wiki_words.rb +23 -25
  27. data/app/views/{wiki/new_system.rhtml → admin/create_system.rhtml} +83 -78
  28. data/app/views/{wiki/new_web.rhtml → admin/create_web.rhtml} +69 -64
  29. data/app/views/admin/edit_web.rhtml +136 -0
  30. data/app/views/file/file.rhtml +19 -0
  31. data/app/views/file/import.rhtml +23 -0
  32. data/app/views/layouts/default.rhtml +85 -0
  33. data/app/views/markdown_help.rhtml +12 -16
  34. data/app/views/mixed_help.rhtml +7 -0
  35. data/app/views/navigation.rhtml +30 -19
  36. data/app/views/rdoc_help.rhtml +12 -16
  37. data/app/views/textile_help.rhtml +24 -28
  38. data/app/views/wiki/authors.rhtml +11 -13
  39. data/app/views/wiki/edit.rhtml +39 -31
  40. data/app/views/wiki/export.rhtml +12 -14
  41. data/app/views/wiki/feeds.rhtml +14 -10
  42. data/app/views/wiki/list.rhtml +64 -57
  43. data/app/views/wiki/locked.rhtml +23 -14
  44. data/app/views/wiki/login.rhtml +14 -11
  45. data/app/views/wiki/new.rhtml +31 -27
  46. data/app/views/wiki/page.rhtml +115 -81
  47. data/app/views/wiki/print.rhtml +14 -16
  48. data/app/views/wiki/published.rhtml +9 -10
  49. data/app/views/wiki/recently_revised.rhtml +27 -30
  50. data/app/views/wiki/revision.rhtml +103 -81
  51. data/app/views/wiki/rollback.rhtml +14 -9
  52. data/app/views/wiki/rss_feed.rhtml +22 -22
  53. data/app/views/wiki/search.rhtml +38 -15
  54. data/app/views/wiki/tex.rhtml +22 -22
  55. data/app/views/wiki/tex_web.rhtml +34 -34
  56. data/app/views/wiki/web_list.rhtml +18 -13
  57. data/app/views/wiki_words_help.rhtml +9 -8
  58. data/config/environment.rb +82 -0
  59. data/config/environments/development.rb +5 -0
  60. data/config/environments/production.rb +4 -0
  61. data/config/environments/test.rb +17 -0
  62. data/config/routes.rb +18 -0
  63. data/instiki +6 -67
  64. data/instiki.rb +3 -0
  65. data/lib/active_record_stub.rb +31 -0
  66. data/{libraries/diff → lib}/diff.rb +444 -475
  67. data/lib/instiki_errors.rb +15 -0
  68. data/{libraries → lib}/rdocsupport.rb +151 -155
  69. data/lib/redcloth_for_tex.rb +736 -0
  70. data/natives/osx/desktop_launcher/AppDelegate.h +18 -0
  71. data/natives/osx/desktop_launcher/AppDelegate.mm +109 -0
  72. data/natives/osx/desktop_launcher/Credits.html +16 -0
  73. data/natives/osx/desktop_launcher/English.lproj/InfoPlist.strings +0 -0
  74. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/classes.nib +13 -0
  75. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/info.nib +24 -0
  76. data/natives/osx/desktop_launcher/English.lproj/MainMenu.nib/objects.nib +0 -0
  77. data/natives/osx/desktop_launcher/Info.plist +13 -0
  78. data/natives/osx/desktop_launcher/Instiki.xcode/project.pbxproj +592 -0
  79. data/natives/osx/desktop_launcher/Instiki_Prefix.pch +7 -0
  80. data/natives/osx/desktop_launcher/MakeDMG.sh +9 -0
  81. data/natives/osx/desktop_launcher/main.mm +14 -0
  82. data/natives/osx/desktop_launcher/version.plist +16 -0
  83. data/public/404.html +6 -0
  84. data/public/500.html +6 -0
  85. data/public/dispatch.rb +10 -0
  86. data/public/favicon.ico +0 -0
  87. data/public/javascripts/edit_web.js +52 -0
  88. data/public/javascripts/prototype.js +336 -0
  89. data/{app/views/static_style_sheet.rhtml → public/stylesheets/instiki.css} +221 -198
  90. data/script/breakpointer +4 -0
  91. data/script/server +93 -0
  92. metadata +59 -32
  93. data/app/controllers/wiki.rb +0 -389
  94. data/app/models/chunks/match.rb +0 -19
  95. data/app/views/bottom.rhtml +0 -4
  96. data/app/views/top.rhtml +0 -49
  97. data/app/views/wiki/edit_web.rhtml +0 -138
  98. data/libraries/action_controller_servlet.rb +0 -177
  99. data/libraries/erb.rb +0 -490
  100. data/libraries/madeleine_service.rb +0 -68
  101. data/libraries/redcloth_for_tex.rb +0 -869
  102. data/libraries/web_controller_server.rb +0 -81
@@ -0,0 +1,7 @@
1
+ //
2
+ // Prefix header for all source files of the 'Instiki' target in the 'Instiki' project
3
+ //
4
+
5
+ #ifdef __OBJC__
6
+ #import <Cocoa/Cocoa.h>
7
+ #endif
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+
3
+ hdiutil create -size 12m -fs HFS+ -volname Instiki -ov /tmp/Instiki_12MB.dmg
4
+ hdiutil mount /tmp/Instiki_12MB.dmg
5
+ # strip ~/ruby/instiki/natives/osx/build/Instiki.app/Contents/MacOS/Instiki
6
+ ditto ~/ruby/instiki/natives/osx/desktop_launcher/build/Instiki.app /Volumes/Instiki/Instiki.app
7
+ hdiutil unmount /Volumes/Instiki
8
+ hdiutil convert -format UDZO -o /tmp/Instiki.dmg /tmp/Instiki_12MB.dmg
9
+ hdiutil internet-enable -yes /tmp/Instiki.dmg
@@ -0,0 +1,14 @@
1
+ //
2
+ // main.mm
3
+ // Instiki
4
+ //
5
+ // Created by Allan Odgaard on Thu May 20 2004.
6
+ // Copyright (c) 2004 MacroMates. All rights reserved.
7
+ //
8
+
9
+ #import <Cocoa/Cocoa.h>
10
+
11
+ int main (int argc, char const* argv[])
12
+ {
13
+ return NSApplicationMain(argc, argv);
14
+ }
@@ -0,0 +1,16 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>BuildVersion</key>
6
+ <string>17</string>
7
+ <key>CFBundleShortVersionString</key>
8
+ <string>0.1</string>
9
+ <key>CFBundleVersion</key>
10
+ <string>0.1</string>
11
+ <key>ProjectName</key>
12
+ <string>NibPBTemplates</string>
13
+ <key>SourceVersion</key>
14
+ <string>1150000</string>
15
+ </dict>
16
+ </plist>
@@ -0,0 +1,6 @@
1
+ <html>
2
+ <body>
3
+ <h1>File not found</h1>
4
+ <p>Change this error message for pages not found in public/404.html</p>
5
+ </body>
6
+ </html>
@@ -0,0 +1,6 @@
1
+ <html>
2
+ <body>
3
+ <h1>Application error (Apache)</h1>
4
+ <p>Change this error message for exceptions thrown outside of an action (like in Dispatcher setups or broken Ruby code) in public/500.html</p>
5
+ </body>
6
+ </html>
@@ -0,0 +1,10 @@
1
+ #!e:/ruby/bin/ruby
2
+
3
+ require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
4
+
5
+ # If you're using RubyGems and mod_ruby, this require should be changed to an absolute path one, like:
6
+ # "/usr/local/lib/ruby/gems/1.8/gems/rails-0.8.0/lib/dispatcher" -- otherwise performance is severely impaired
7
+ require "dispatcher"
8
+
9
+ ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
10
+ Dispatcher.dispatch
Binary file
@@ -0,0 +1,52 @@
1
+ function proposeAddress() {
2
+ document.getElementById('address').value =
3
+ document.getElementById('name').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
4
+ }
5
+
6
+ function cleanAddress() {
7
+ document.getElementById('address').value =
8
+ document.getElementById('address').value.replace(/[^a-zA-Z0-9]/g, "").toLowerCase();
9
+ }
10
+
11
+ function checkSystemPassword(password) {
12
+ if (password == "") {
13
+ alert("You must enter the system password");
14
+ return false;
15
+ } else {
16
+ return true;
17
+ }
18
+ }
19
+
20
+ function validateEditWebForm() {
21
+ if (!checkSystemPassword(document.getElementById('system_password').value)) {
22
+ return false;
23
+ }
24
+ if (document.getElementById('name').value == "") {
25
+ alert("You must pick a name for the web");
26
+ return false;
27
+ }
28
+ if (document.getElementById('address').value == "") {
29
+ alert("You must pick an address for the web");
30
+ return false;
31
+ }
32
+ if (document.getElementById('password').value != "" &&
33
+ document.getElementById('password').value != document.getElementById('password_check').value) {
34
+ alert("The password and its verification doesn't match");
35
+ return false;
36
+ }
37
+ return true;
38
+ }
39
+
40
+ // overriding auto-complete by form managers
41
+ // code by Chris Holland, lifted from
42
+ // http://chrisholland.blogspot.com/2004/11/banks-protect-privacy-disable.html
43
+ function overrideAutocomplete() {
44
+ if (document.getElementsByTagName) {
45
+ var inputElements = document.getElementsByTagName("input");
46
+ for (i=0; inputElements[i]; i++) {
47
+ if (inputElements[i].className && (inputElements[i].className.indexOf("disableAutoComplete") != -1)) {
48
+ inputElements[i].setAttribute("autocomplete","off");
49
+ }//if current input element has the disableAutoComplete class set.
50
+ }//loop thru input elements
51
+ }
52
+ }
@@ -0,0 +1,336 @@
1
+ /* Prototype: an object-oriented Javascript library, version 1.0.1
2
+ * (c) 2005 Sam Stephenson <sam@conio.net>
3
+ *
4
+ * Prototype is freely distributable under the terms of an MIT-style license.
5
+ * For details, see http://prototype.conio.net/
6
+ */
7
+
8
+ Prototype = {
9
+ Version: '1.0.1'
10
+ }
11
+
12
+ Class = {
13
+ create: function() {
14
+ return function() {
15
+ this.initialize.apply(this, arguments);
16
+ }
17
+ }
18
+ }
19
+
20
+ Abstract = new Object();
21
+
22
+ Object.prototype.extend = function(object) {
23
+ for (property in object) {
24
+ this[property] = object[property];
25
+ }
26
+ return this;
27
+ }
28
+
29
+ Function.prototype.bind = function(object) {
30
+ var method = this;
31
+ return function() {
32
+ method.apply(object, arguments);
33
+ }
34
+ }
35
+
36
+ Function.prototype.bindAsEventListener = function(object) {
37
+ var method = this;
38
+ return function(event) {
39
+ method.call(object, event || window.event);
40
+ }
41
+ }
42
+
43
+ Try = {
44
+ these: function() {
45
+ var returnValue;
46
+
47
+ for (var i = 0; i < arguments.length; i++) {
48
+ var lambda = arguments[i];
49
+ try {
50
+ returnValue = lambda();
51
+ break;
52
+ } catch (e) {}
53
+ }
54
+
55
+ return returnValue;
56
+ }
57
+ }
58
+
59
+ Toggle = {
60
+ display: function() {
61
+ for (var i = 0; i < elements.length; i++) {
62
+ var element = $(elements[i]);
63
+ element.style.display =
64
+ (element.style.display == 'none' ? '' : 'none');
65
+ }
66
+ }
67
+ }
68
+
69
+ /*--------------------------------------------------------------------------*/
70
+
71
+ function $() {
72
+ var elements = new Array();
73
+
74
+ for (var i = 0; i < arguments.length; i++) {
75
+ var element = arguments[i];
76
+ if (typeof element == 'string')
77
+ element = document.getElementById(element);
78
+
79
+ if (arguments.length == 1)
80
+ return element;
81
+
82
+ elements.push(element);
83
+ }
84
+
85
+ return elements;
86
+ }
87
+
88
+ function getElementsByClassName(className, element) {
89
+ var children = (element || document).getElementsByTagName('*');
90
+ var elements = new Array();
91
+
92
+ for (var i = 0; i < children.length; i++) {
93
+ var child = children[i];
94
+ var classNames = child.className.split(' ');
95
+ for (var j = 0; j < classNames.length; j++) {
96
+ if (classNames[j] == className) {
97
+ elements.push(child);
98
+ break;
99
+ }
100
+ }
101
+ }
102
+
103
+ return elements;
104
+ }
105
+
106
+ /*--------------------------------------------------------------------------*/
107
+
108
+ Ajax = {
109
+ getTransport: function() {
110
+ return Try.these(
111
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
112
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')},
113
+ function() {return new XMLHttpRequest()}
114
+ ) || false;
115
+ },
116
+
117
+ emptyFunction: function() {}
118
+ }
119
+
120
+ Ajax.Base = function() {};
121
+ Ajax.Base.prototype = {
122
+ setOptions: function(options) {
123
+ this.options = {
124
+ method: 'post',
125
+ asynchronous: true,
126
+ parameters: ''
127
+ }.extend(options || {});
128
+ }
129
+ }
130
+
131
+ Ajax.Request = Class.create();
132
+ Ajax.Request.Events =
133
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
134
+
135
+ Ajax.Request.prototype = (new Ajax.Base()).extend({
136
+ initialize: function(url, options) {
137
+ this.transport = Ajax.getTransport();
138
+ this.setOptions(options);
139
+
140
+ try {
141
+ if (this.options.method == 'get')
142
+ url += '?' + this.options.parameters + '&_=';
143
+
144
+ this.transport.open(this.options.method, url, true);
145
+
146
+ if (this.options.asynchronous) {
147
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
148
+ setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
149
+ }
150
+
151
+ if (this.options.method == 'post') {
152
+ this.transport.setRequestHeader('Connection', 'close');
153
+ this.transport.setRequestHeader('Content-type',
154
+ 'application/x-www-form-urlencoded');
155
+ }
156
+
157
+ this.transport.send(this.options.method == 'post' ?
158
+ this.options.parameters + '&_=' : null);
159
+
160
+ } catch (e) {
161
+ }
162
+ },
163
+
164
+ onStateChange: function() {
165
+ var readyState = this.transport.readyState;
166
+ if (readyState != 1)
167
+ this.respondToReadyState(this.transport.readyState);
168
+ },
169
+
170
+ respondToReadyState: function(readyState) {
171
+ var event = Ajax.Request.Events[readyState];
172
+ (this.options['on' + event] || Ajax.emptyFunction)(this.transport);
173
+ }
174
+ });
175
+
176
+ Ajax.Updater = Class.create();
177
+ Ajax.Updater.prototype = (new Ajax.Base()).extend({
178
+ initialize: function(container, url, options) {
179
+ this.container = $(container);
180
+ this.setOptions(options);
181
+
182
+ if (this.options.asynchronous) {
183
+ this.onComplete = this.options.onComplete;
184
+ this.options.onComplete = this.updateContent.bind(this);
185
+ }
186
+
187
+ this.request = new Ajax.Request(url, this.options);
188
+
189
+ if (!this.options.asynchronous)
190
+ this.updateContent();
191
+ },
192
+
193
+ updateContent: function() {
194
+ this.container.innerHTML = this.request.transport.responseText;
195
+ if (this.onComplete) this.onComplete(this.request);
196
+ }
197
+ });
198
+
199
+ /*--------------------------------------------------------------------------*/
200
+
201
+ Field = {
202
+ clear: function() {
203
+ for (var i = 0; i < arguments.length; i++)
204
+ $(arguments[i]).value = '';
205
+ },
206
+
207
+ focus: function(element) {
208
+ $(element).focus();
209
+ },
210
+
211
+ present: function() {
212
+ for (var i = 0; i < arguments.length; i++)
213
+ if ($(arguments[i]).value == '') return false;
214
+ return true;
215
+ }
216
+ }
217
+
218
+ /*--------------------------------------------------------------------------*/
219
+
220
+ Form = {
221
+ serialize: function(form) {
222
+ var elements = Form.getElements($(form));
223
+ var queryComponents = new Array();
224
+
225
+ for (var i = 0; i < elements.length; i++) {
226
+ var queryComponent = Form.Element.serialize(elements[i]);
227
+ if (queryComponent)
228
+ queryComponents.push(queryComponent);
229
+ }
230
+
231
+ return queryComponents.join('&');
232
+ },
233
+
234
+ getElements: function(form) {
235
+ form = $(form);
236
+ var elements = new Array();
237
+
238
+ for (tagName in Form.Element.Serializers) {
239
+ var tagElements = form.getElementsByTagName(tagName);
240
+ for (var j = 0; j < tagElements.length; j++)
241
+ elements.push(tagElements[j]);
242
+ }
243
+ return elements;
244
+ }
245
+ }
246
+
247
+ Form.Element = {
248
+ serialize: function(element) {
249
+ element = $(element);
250
+ var method = element.tagName.toLowerCase();
251
+ var parameter = Form.Element.Serializers[method](element);
252
+
253
+ if (parameter)
254
+ return encodeURIComponent(parameter[0]) + '=' +
255
+ encodeURIComponent(parameter[1]);
256
+ },
257
+
258
+ getValue: function(element) {
259
+ element = $(element);
260
+ var method = element.tagName.toLowerCase();
261
+ var parameter = Form.Element.Serializers[method](element);
262
+
263
+ if (parameter)
264
+ return parameter[1];
265
+ }
266
+ }
267
+
268
+ Form.Element.Serializers = {
269
+ input: function(element) {
270
+ switch (element.type.toLowerCase()) {
271
+ case 'hidden':
272
+ case 'text':
273
+ return Form.Element.Serializers.textarea(element);
274
+ case 'checkbox':
275
+ case 'radio':
276
+ return Form.Element.Serializers.inputSelector(element);
277
+ }
278
+ },
279
+
280
+ inputSelector: function(element) {
281
+ if (element.checked)
282
+ return [element.name, element.value];
283
+ },
284
+
285
+ textarea: function(element) {
286
+ return [element.name, element.value];
287
+ },
288
+
289
+ select: function(element) {
290
+ var index = element.selectedIndex;
291
+ return [element.name, (index >= 0) ? element.options[index].value : ''];
292
+ }
293
+ }
294
+
295
+ /*--------------------------------------------------------------------------*/
296
+
297
+ Abstract.TimedObserver = function() {}
298
+ Abstract.TimedObserver.prototype = {
299
+ initialize: function(element, frequency, callback) {
300
+ this.frequency = frequency;
301
+ this.element = $(element);
302
+ this.callback = callback;
303
+
304
+ this.lastValue = this.getValue();
305
+ this.registerCallback();
306
+ },
307
+
308
+ registerCallback: function() {
309
+ setTimeout(this.onTimerEvent.bind(this), this.frequency * 1000);
310
+ },
311
+
312
+ onTimerEvent: function() {
313
+ var value = this.getValue();
314
+ if (this.lastValue != value) {
315
+ this.callback(this.element, value);
316
+ this.lastValue = value;
317
+ }
318
+
319
+ this.registerCallback();
320
+ }
321
+ }
322
+
323
+ Form.Element.Observer = Class.create();
324
+ Form.Element.Observer.prototype = (new Abstract.TimedObserver()).extend({
325
+ getValue: function() {
326
+ return Form.Element.getValue(this.element);
327
+ }
328
+ });
329
+
330
+ Form.Observer = Class.create();
331
+ Form.Observer.prototype = (new Abstract.TimedObserver()).extend({
332
+ getValue: function() {
333
+ return Form.serialize(this.element);
334
+ }
335
+ });
336
+