gollum-bibanon 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. data/Gemfile +4 -0
  2. data/HISTORY.md +93 -0
  3. data/Home.md +3 -0
  4. data/LICENSE +21 -0
  5. data/README.md +483 -0
  6. data/Rakefile +138 -0
  7. data/bin/gollum +126 -0
  8. data/docs/sanitization.md +32 -0
  9. data/gollum.gemspec +212 -0
  10. data/lib/gollum.rb +40 -0
  11. data/lib/gollum/blob_entry.rb +78 -0
  12. data/lib/gollum/committer.rb +218 -0
  13. data/lib/gollum/file.rb +64 -0
  14. data/lib/gollum/frontend/app.rb +234 -0
  15. data/lib/gollum/frontend/public/css/dialog.css +141 -0
  16. data/lib/gollum/frontend/public/css/editor.css +537 -0
  17. data/lib/gollum/frontend/public/css/gollum.css +660 -0
  18. data/lib/gollum/frontend/public/css/ie7.css +69 -0
  19. data/lib/gollum/frontend/public/css/template.css +381 -0
  20. data/lib/gollum/frontend/public/images/icon-sprite.png +0 -0
  21. data/lib/gollum/frontend/public/javascript/editor/gollum.editor.js +1073 -0
  22. data/lib/gollum/frontend/public/javascript/editor/langs/asciidoc.js +167 -0
  23. data/lib/gollum/frontend/public/javascript/editor/langs/creole.js +104 -0
  24. data/lib/gollum/frontend/public/javascript/editor/langs/markdown.js +211 -0
  25. data/lib/gollum/frontend/public/javascript/editor/langs/org.js +173 -0
  26. data/lib/gollum/frontend/public/javascript/editor/langs/pod.js +111 -0
  27. data/lib/gollum/frontend/public/javascript/editor/langs/rdoc.js +74 -0
  28. data/lib/gollum/frontend/public/javascript/editor/langs/textile.js +175 -0
  29. data/lib/gollum/frontend/public/javascript/gollum.dialog.js +263 -0
  30. data/lib/gollum/frontend/public/javascript/gollum.js +161 -0
  31. data/lib/gollum/frontend/public/javascript/gollum.placeholder.js +54 -0
  32. data/lib/gollum/frontend/public/javascript/jquery.color.js +123 -0
  33. data/lib/gollum/frontend/public/javascript/jquery.js +7179 -0
  34. data/lib/gollum/frontend/templates/compare.mustache +53 -0
  35. data/lib/gollum/frontend/templates/create.mustache +15 -0
  36. data/lib/gollum/frontend/templates/edit.mustache +17 -0
  37. data/lib/gollum/frontend/templates/editor.mustache +116 -0
  38. data/lib/gollum/frontend/templates/error.mustache +8 -0
  39. data/lib/gollum/frontend/templates/history.mustache +60 -0
  40. data/lib/gollum/frontend/templates/layout.mustache +28 -0
  41. data/lib/gollum/frontend/templates/page.mustache +45 -0
  42. data/lib/gollum/frontend/templates/pages.mustache +35 -0
  43. data/lib/gollum/frontend/templates/search.mustache +36 -0
  44. data/lib/gollum/frontend/templates/searchbar.mustache +10 -0
  45. data/lib/gollum/frontend/views/compare.rb +94 -0
  46. data/lib/gollum/frontend/views/create.rb +44 -0
  47. data/lib/gollum/frontend/views/edit.rb +52 -0
  48. data/lib/gollum/frontend/views/editable.rb +13 -0
  49. data/lib/gollum/frontend/views/error.rb +7 -0
  50. data/lib/gollum/frontend/views/history.rb +44 -0
  51. data/lib/gollum/frontend/views/layout.rb +20 -0
  52. data/lib/gollum/frontend/views/page.rb +57 -0
  53. data/lib/gollum/frontend/views/pages.rb +19 -0
  54. data/lib/gollum/frontend/views/search.rb +20 -0
  55. data/lib/gollum/git_access.rb +248 -0
  56. data/lib/gollum/markup.rb +432 -0
  57. data/lib/gollum/page.rb +428 -0
  58. data/lib/gollum/pagination.rb +61 -0
  59. data/lib/gollum/sanitization.rb +161 -0
  60. data/lib/gollum/wiki.rb +636 -0
  61. data/templates/formatting.html +92 -0
  62. data/test/examples/empty.git/HEAD +1 -0
  63. data/test/examples/empty.git/config +5 -0
  64. data/test/examples/empty.git/description +1 -0
  65. data/test/examples/empty.git/hooks/applypatch-msg.sample +15 -0
  66. data/test/examples/empty.git/hooks/commit-msg.sample +24 -0
  67. data/test/examples/empty.git/hooks/post-commit.sample +8 -0
  68. data/test/examples/empty.git/hooks/post-receive.sample +15 -0
  69. data/test/examples/empty.git/hooks/post-update.sample +8 -0
  70. data/test/examples/empty.git/hooks/pre-applypatch.sample +14 -0
  71. data/test/examples/empty.git/hooks/pre-commit.sample +46 -0
  72. data/test/examples/empty.git/hooks/pre-rebase.sample +169 -0
  73. data/test/examples/empty.git/hooks/prepare-commit-msg.sample +36 -0
  74. data/test/examples/empty.git/hooks/update.sample +128 -0
  75. data/test/examples/empty.git/info/exclude +6 -0
  76. data/test/examples/lotr.git/COMMIT_EDITMSG +1 -0
  77. data/test/examples/lotr.git/HEAD +1 -0
  78. data/test/examples/lotr.git/config +12 -0
  79. data/test/examples/lotr.git/description +1 -0
  80. data/test/examples/lotr.git/index +0 -0
  81. data/test/examples/lotr.git/info/exclude +6 -0
  82. data/test/examples/lotr.git/logs/HEAD +3 -0
  83. data/test/examples/lotr.git/logs/refs/heads/master +3 -0
  84. data/test/examples/lotr.git/objects/06/131480411710c92a82fe2d1e76932c70feb2e5 +0 -0
  85. data/test/examples/lotr.git/objects/0a/de1e2916346d4c1f2fb63b863fd3c16808fe44 +0 -0
  86. data/test/examples/lotr.git/objects/0e/d8cbe0a25235bd867e65193c7d837c66b328ef +3 -0
  87. data/test/examples/lotr.git/objects/24/49c2681badfd3c189e8ed658dacffe8ba48fe5 +0 -0
  88. data/test/examples/lotr.git/objects/2c/b9156ad383914561a8502fc70f5a1d887e48ad +4 -0
  89. data/test/examples/lotr.git/objects/5d/cac289a8603188d2c5caf481dcba2985126aaa +0 -0
  90. data/test/examples/lotr.git/objects/60/f12f4254f58801b9ee7db7bca5fa8aeefaa56b +0 -0
  91. data/test/examples/lotr.git/objects/71/4323c104239440a5c66ab12a67ed07a83c404f +0 -0
  92. data/test/examples/lotr.git/objects/84/0ec5b1ba1320e8ec443f28f99566f615d5af10 +0 -0
  93. data/test/examples/lotr.git/objects/93/6b83ee0dd8837adb82511e40d5e4ebe59bb675 +0 -0
  94. data/test/examples/lotr.git/objects/94/523d7ae48aeba575099dd12926420d8fd0425d +2 -0
  95. data/test/examples/lotr.git/objects/96/97dc65e095658bbd1b8e8678e08881e86d32f1 +0 -0
  96. data/test/examples/lotr.git/objects/a3/1ca2a7c352c92531a8b99815d15843b259e814 +0 -0
  97. data/test/examples/lotr.git/objects/a8/ad3c09dd842a3517085bfadd37718856dee813 +0 -0
  98. data/test/examples/lotr.git/objects/aa/b61fe89d56f8614c0a8151da34f939dcedfa68 +0 -0
  99. data/test/examples/lotr.git/objects/c3/b43e9f08966b088e7a0192e436b7a884542e05 +0 -0
  100. data/test/examples/lotr.git/objects/dc/596d6b2dd89ab05c66f4abd7d5eb706bc17f19 +0 -0
  101. data/test/examples/lotr.git/objects/ec/da3205bee14520aab5a7bb307392064b938e83 +0 -0
  102. data/test/examples/lotr.git/objects/fa/e7ef5344202bba4129abdc13060d9297d99465 +3 -0
  103. data/test/examples/lotr.git/objects/info/packs +2 -0
  104. data/test/examples/lotr.git/objects/pack/pack-dcbeaf3f6ff6c5eb08ea2b0a2d83626e8763546b.idx +0 -0
  105. data/test/examples/lotr.git/objects/pack/pack-dcbeaf3f6ff6c5eb08ea2b0a2d83626e8763546b.pack +0 -0
  106. data/test/examples/lotr.git/packed-refs +2 -0
  107. data/test/examples/lotr.git/refs/heads/master +1 -0
  108. data/test/examples/lotr.git/refs/remotes/origin/HEAD +1 -0
  109. data/test/examples/page_file_dir.git/COMMIT_EDITMSG +1 -0
  110. data/test/examples/page_file_dir.git/HEAD +1 -0
  111. data/test/examples/page_file_dir.git/config +6 -0
  112. data/test/examples/page_file_dir.git/description +1 -0
  113. data/test/examples/page_file_dir.git/index +0 -0
  114. data/test/examples/page_file_dir.git/info/exclude +6 -0
  115. data/test/examples/page_file_dir.git/logs/HEAD +1 -0
  116. data/test/examples/page_file_dir.git/logs/refs/heads/master +1 -0
  117. data/test/examples/page_file_dir.git/objects/0c/7d27db1f575263efdcab3dc650f4502a2dbcbf +0 -0
  118. data/test/examples/page_file_dir.git/objects/22/b404803c966dd92865614d86ff22ca12e50c1e +0 -0
  119. data/test/examples/page_file_dir.git/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99 +0 -0
  120. data/test/examples/page_file_dir.git/objects/57/16ca5987cbf97d6bb54920bea6adde242d87e6 +0 -0
  121. data/test/examples/page_file_dir.git/objects/5b/43e14e0a15fb6f08feab1773d1c0991e9f71e2 +0 -0
  122. data/test/examples/page_file_dir.git/refs/heads/master +1 -0
  123. data/test/examples/revert.git/COMMIT_EDITMSG +1 -0
  124. data/test/examples/revert.git/HEAD +1 -0
  125. data/test/examples/revert.git/config +12 -0
  126. data/test/examples/revert.git/description +1 -0
  127. data/test/examples/revert.git/index +0 -0
  128. data/test/examples/revert.git/info/exclude +6 -0
  129. data/test/examples/revert.git/logs/HEAD +2 -0
  130. data/test/examples/revert.git/logs/refs/heads/master +2 -0
  131. data/test/examples/revert.git/objects/20/2ced67cea93c7b6bd2928aa1daef8d1d55a20d +0 -0
  132. data/test/examples/revert.git/objects/41/76394bfa11222363c66ce7e84b5f154095b6d9 +0 -0
  133. data/test/examples/revert.git/objects/6a/69f92020f5df77af6e8813ff1232493383b708 +0 -0
  134. data/test/examples/revert.git/objects/b4/785957bc986dc39c629de9fac9df46972c00fc +0 -0
  135. data/test/examples/revert.git/objects/f4/03b791119f8232b7cb0ba455c624ac6435f433 +0 -0
  136. data/test/examples/revert.git/objects/info/packs +2 -0
  137. data/test/examples/revert.git/objects/pack/pack-a561f8437234f74d0bacb9e0eebe52d207f5770d.idx +0 -0
  138. data/test/examples/revert.git/objects/pack/pack-a561f8437234f74d0bacb9e0eebe52d207f5770d.pack +0 -0
  139. data/test/examples/revert.git/packed-refs +2 -0
  140. data/test/examples/revert.git/refs/heads/master +1 -0
  141. data/test/examples/revert.git/refs/remotes/origin/HEAD +1 -0
  142. data/test/examples/yubiwa.git/HEAD +1 -0
  143. data/test/examples/yubiwa.git/config +5 -0
  144. data/test/examples/yubiwa.git/description +1 -0
  145. data/test/examples/yubiwa.git/info/exclude +6 -0
  146. data/test/examples/yubiwa.git/objects/10/fa2ddc4e3b4009d8a453aace10bd6148c1ad00 +0 -0
  147. data/test/examples/yubiwa.git/objects/52/4b82874327ea7cbf730389964ba7cb3de966de +0 -0
  148. data/test/examples/yubiwa.git/objects/58/3fc201cb457fb3f1480f3e1e5999b119633835 +0 -0
  149. data/test/examples/yubiwa.git/objects/87/bc1dd46ab3d3874d4e898d45dd512cc20a7cc8 +1 -0
  150. data/test/examples/yubiwa.git/objects/89/64ed1b4e21aa90e831763bbce9034bfda81b70 +0 -0
  151. data/test/examples/yubiwa.git/objects/9f/f6dd0660da5fba2d3374adb2b84fa653bb538b +0 -0
  152. data/test/examples/yubiwa.git/objects/ac/e97abf2b177815a1972d7db22f229f58c83309 +0 -0
  153. data/test/examples/yubiwa.git/objects/b1/f443863a4816628807fbf86141ebef055dda34 +0 -0
  154. data/test/examples/yubiwa.git/refs/heads/master +1 -0
  155. data/test/helper.rb +66 -0
  156. data/test/test_app.rb +179 -0
  157. data/test/test_committer.rb +64 -0
  158. data/test/test_file.rb +27 -0
  159. data/test/test_git_access.rb +52 -0
  160. data/test/test_markup.rb +580 -0
  161. data/test/test_page.rb +166 -0
  162. data/test/test_page_revert.rb +45 -0
  163. data/test/test_wiki.rb +462 -0
  164. metadata +493 -0
@@ -0,0 +1,1073 @@
1
+ /**
2
+ * gollum.editor.js
3
+ * A jQuery plugin that creates the Gollum Editor.
4
+ *
5
+ * Usage:
6
+ * $.GollumEditor(); on DOM ready.
7
+ */
8
+ (function($) {
9
+
10
+ // Editor options
11
+ var DefaultOptions = {
12
+ MarkupType: 'markdown',
13
+ EditorMode: 'code',
14
+ NewFile: false,
15
+ HasFunctionBar: true,
16
+ Debug: false,
17
+ NoDefinitionsFor: []
18
+ };
19
+ var ActiveOptions = {};
20
+
21
+ /**
22
+ * $.GollumEditor
23
+ *
24
+ * You don't need to do anything. Just run this on DOM ready.
25
+ */
26
+ $.GollumEditor = function( IncomingOptions ) {
27
+
28
+ ActiveOptions = $.extend( DefaultOptions, IncomingOptions );
29
+
30
+ debug('GollumEditor loading');
31
+
32
+ if ( EditorHas.baseEditorMarkup() ) {
33
+
34
+ if ( EditorHas.titleDisplayed() ) {
35
+ $('#gollum-editor-title-field').addClass('active');
36
+ }
37
+
38
+ if ( EditorHas.editSummaryMarkup() ) {
39
+ $.GollumEditor.Placeholder.add($('#gollum-editor-edit-summary input'));
40
+ $('#gollum-editor form[name="gollum-editor"]').submit(function( e ) {
41
+ e.preventDefault();
42
+ $.GollumEditor.Placeholder.clearAll();
43
+ debug('submitting');
44
+ $(this).unbind('submit');
45
+ $(this).submit();
46
+ });
47
+ }
48
+
49
+ if ( EditorHas.collapsibleInputs() ) {
50
+ $('#gollum-editor .collapsed a.button, ' +
51
+ '#gollum-editor .expanded a.button').click(function( e ) {
52
+ e.preventDefault();
53
+ $(this).parent().toggleClass('expanded');
54
+ $(this).parent().toggleClass('collapsed');
55
+ });
56
+ }
57
+
58
+ if ( EditorHas.previewButton() ) {
59
+ var formAction =
60
+ $('#gollum-editor #gollum-editor-preview').click(function() {
61
+ // make a dummy form, submit to new target window
62
+ // get form fields
63
+ var oldAction = $('#gollum-editor form').attr('action');
64
+ var $form = $($('#gollum-editor form').get(0));
65
+ $form.attr('action', this.href || '/preview');
66
+ $form.attr('target', '_blank');
67
+ $form.submit();
68
+
69
+
70
+ $form.attr('action', oldAction);
71
+ $form.removeAttr('target');
72
+ return false;
73
+ });
74
+ }
75
+
76
+ // Initialize the function bar by loading proper definitions
77
+ if ( EditorHas.functionBar() ) {
78
+
79
+ var htmlSetMarkupLang =
80
+ $('#gollum-editor-body').attr('data-markup-lang');
81
+
82
+ if ( htmlSetMarkupLang ) {
83
+ ActiveOptions.MarkupType = htmlSetMarkupLang;
84
+ }
85
+
86
+ // load language definition
87
+ LanguageDefinition.setActiveLanguage( ActiveOptions.MarkupType );
88
+ if ( EditorHas.formatSelector() ) {
89
+ FormatSelector.init(
90
+ $('#gollum-editor-format-selector select') );
91
+ }
92
+
93
+ if ( EditorHas.help() ) {
94
+ $('#gollum-editor-help').hide();
95
+ $('#gollum-editor-help').removeClass('jaws');
96
+ }
97
+
98
+ }
99
+ // EditorHas.functionBar
100
+ }
101
+ // EditorHas.baseEditorMarkup
102
+ };
103
+
104
+
105
+
106
+ /**
107
+ * $.GollumEditor.defineLanguage
108
+ * Defines a set of language actions that Gollum can use.
109
+ * Used by the definitions in langs/ to register language definitions.
110
+ */
111
+ $.GollumEditor.defineLanguage = function( language_name, languageObject ) {
112
+ if ( typeof languageObject == 'object' ) {
113
+ LanguageDefinition.define( language_name, languageObject );
114
+ } else {
115
+ debug('GollumEditor.defineLanguage: definition for ' + language_name +
116
+ ' is not an object');
117
+ }
118
+ };
119
+
120
+
121
+ /**
122
+ * debug
123
+ * Prints debug information to console.log if debug output is enabled.
124
+ *
125
+ * @param mixed Whatever you want to dump to console.log
126
+ * @return void
127
+ */
128
+ var debug = function(m) {
129
+ if ( ActiveOptions.Debug &&
130
+ typeof console != 'undefined' ) {
131
+ console.log( m );
132
+ }
133
+ };
134
+
135
+
136
+
137
+ /**
138
+ * LanguageDefinition
139
+ * Language definition file handler
140
+ * Loads language definition files as necessary.
141
+ */
142
+ var LanguageDefinition = {
143
+
144
+ _ACTIVE_LANG: '',
145
+ _LOADED_LANGS: [],
146
+ _LANG: {},
147
+
148
+ /**
149
+ * Defines a language
150
+ *
151
+ * @param name string The name of the language
152
+ * @param name object The definition object
153
+ */
154
+ define: function( name, definitionObject ) {
155
+ LanguageDefinition._ACTIVE_LANG = name;
156
+ LanguageDefinition._LOADED_LANGS.push( name );
157
+ if ( typeof $.GollumEditor.WikiLanguage == 'object' ) {
158
+ var definition = {};
159
+ $.extend(definition, $.GollumEditor.WikiLanguage, definitionObject);
160
+ LanguageDefinition._LANG[name] = definition;
161
+ } else {
162
+ LanguageDefinition._LANG[name] = definitionObject;
163
+ }
164
+ },
165
+
166
+ getActiveLanguage: function() {
167
+ return LanguageDefinition._ACTIVE_LANG;
168
+ },
169
+
170
+ setActiveLanguage: function( name ) {
171
+ if ( !LanguageDefinition.isLoadedFor(name) ) {
172
+ LanguageDefinition._ACTIVE_LANG = null;
173
+ LanguageDefinition.loadFor( name, function(x, t) {
174
+ if ( t != 'success' ) {
175
+ debug('Failed to load language definition for ' + name);
176
+ // well, fake it and turn everything off for this one
177
+ LanguageDefinition.define( name, {} );
178
+ }
179
+
180
+ // update features that rely on the language definition
181
+ if ( EditorHas.functionBar() ) {
182
+ FunctionBar.refresh();
183
+ }
184
+
185
+ if ( LanguageDefinition.isValid() && EditorHas.formatSelector() ) {
186
+ FormatSelector.updateSelected();
187
+ }
188
+
189
+ } );
190
+ } else {
191
+ LanguageDefinition._ACTIVE_LANG = name;
192
+ FunctionBar.refresh();
193
+ }
194
+ },
195
+
196
+
197
+ /**
198
+ * gets a definition object for a specified attribute
199
+ *
200
+ * @param string attr The specified attribute.
201
+ * @param string specified_lang The language to pull a definition for.
202
+ * @return object if exists, null otherwise
203
+ */
204
+ getDefinitionFor: function( attr, specified_lang ) {
205
+ if ( !specified_lang ) {
206
+ specified_lang = LanguageDefinition._ACTIVE_LANG;
207
+ }
208
+
209
+ if ( LanguageDefinition.isLoadedFor(specified_lang) &&
210
+ LanguageDefinition._LANG[specified_lang][attr] &&
211
+ typeof LanguageDefinition._LANG[specified_lang][attr] == 'object' ) {
212
+ return LanguageDefinition._LANG[specified_lang][attr];
213
+ }
214
+
215
+ return null;
216
+ },
217
+
218
+
219
+ /**
220
+ * loadFor
221
+ * Asynchronously loads a definition file for the current markup.
222
+ * Definition files are necessary to use the code editor.
223
+ *
224
+ * @param string markup_name The markup name you want to load
225
+ * @return void
226
+ */
227
+ loadFor: function( markup_name, on_complete ) {
228
+ // Keep us from hitting 404s on our site, check the definition blacklist
229
+ if ( ActiveOptions.NoDefinitionsFor.length ) {
230
+ for ( var i=0; i < ActiveOptions.NoDefinitionsFor.length; i++ ) {
231
+ if ( markup_name == ActiveOptions.NoDefinitionsFor[i] ) {
232
+ // we don't have this. get out.
233
+ if ( typeof on_complete == 'function' ) {
234
+ on_complete( null, 'error' );
235
+ return;
236
+ }
237
+ }
238
+ }
239
+ }
240
+
241
+ // attempt to load the definition for this language
242
+ var script_uri = '/javascript/editor/langs/' + markup_name + '.js';
243
+ $.ajax({
244
+ url: script_uri,
245
+ dataType: 'script',
246
+ complete: function( xhr, textStatus ) {
247
+ if ( typeof on_complete == 'function' ) {
248
+ on_complete( xhr, textStatus );
249
+ }
250
+ }
251
+ });
252
+ },
253
+
254
+
255
+ /**
256
+ * isLoadedFor
257
+ * Checks to see if a definition file has been loaded for the
258
+ * specified markup language.
259
+ *
260
+ * @param string markup_name The name of the markup.
261
+ * @return boolean
262
+ */
263
+ isLoadedFor: function( markup_name ) {
264
+ if ( LanguageDefinition._LOADED_LANGS.length === 0 ) {
265
+ return false;
266
+ }
267
+
268
+ for ( var i=0; i < LanguageDefinition._LOADED_LANGS.length; i++ ) {
269
+ if ( LanguageDefinition._LOADED_LANGS[i] == markup_name ) {
270
+ return true;
271
+ }
272
+ }
273
+ return false;
274
+ },
275
+
276
+ isValid: function() {
277
+ return ( LanguageDefinition._ACTIVE_LANG &&
278
+ typeof LanguageDefinition._LANG[LanguageDefinition._ACTIVE_LANG] ==
279
+ 'object' );
280
+ }
281
+
282
+ };
283
+
284
+
285
+ /**
286
+ * EditorHas
287
+ * Various conditionals to check what features of the Gollum Editor are
288
+ * active/operational.
289
+ */
290
+ var EditorHas = {
291
+
292
+
293
+ /**
294
+ * EditorHas.baseEditorMarkup
295
+ * True if the basic editor form is in place.
296
+ *
297
+ * @return boolean
298
+ */
299
+ baseEditorMarkup: function() {
300
+ return ( $('#gollum-editor').length &&
301
+ $('#gollum-editor-body').length );
302
+ },
303
+
304
+
305
+ /**
306
+ * EditorHas.collapsibleInputs
307
+ * True if the editor contains collapsible inputs for things like the
308
+ * sidebar or footer, false otherwise.
309
+ *
310
+ * @return boolean
311
+ */
312
+ collapsibleInputs: function() {
313
+ return $('#gollum-editor .collapsed, #gollum-editor .expanded').length;
314
+ },
315
+
316
+
317
+ /**
318
+ * EditorHas.formatSelector
319
+ * True if the editor has a format selector (for switching between
320
+ * language types), false otherwise.
321
+ *
322
+ * @return boolean
323
+ */
324
+ formatSelector: function() {
325
+ return $('#gollum-editor-format-selector select').length;
326
+ },
327
+
328
+
329
+ /**
330
+ * EditorHas.functionBar
331
+ * True if the Function Bar markup exists.
332
+ *
333
+ * @return boolean
334
+ */
335
+ functionBar: function() {
336
+ return ( ActiveOptions.HasFunctionBar &&
337
+ $('#gollum-editor-function-bar').length );
338
+ },
339
+
340
+
341
+ /**
342
+ * EditorHas.ff4Environment
343
+ * True if in a Firefox 4.0 Beta environment.
344
+ *
345
+ * @return boolean
346
+ */
347
+ ff4Environment: function() {
348
+ var ua = new RegExp(/Firefox\/4.0b/);
349
+ return ( ua.test( navigator.userAgent ) );
350
+ },
351
+
352
+
353
+ /**
354
+ * EditorHas.editSummaryMarkup
355
+ * True if the editor has a summary field (Gollum's commit message),
356
+ * false otherwise.
357
+ *
358
+ * @return boolean
359
+ */
360
+ editSummaryMarkup: function() {
361
+ return ( $('input#gollum-editor-message-field').length > 0 );
362
+ },
363
+
364
+
365
+ /**
366
+ * EditorHas.help
367
+ * True if the editor contains the inline help sector, false otherwise.
368
+ *
369
+ * @return boolean
370
+ */
371
+ help: function() {
372
+ return ( $('#gollum-editor #gollum-editor-help').length &&
373
+ $('#gollum-editor #function-help').length );
374
+ },
375
+
376
+
377
+ /**
378
+ * EditorHas.previewButton
379
+ * True if the editor has a preview button, false otherwise.
380
+ *
381
+ * @return boolean
382
+ */
383
+ previewButton: function() {
384
+ return ( $('#gollum-editor #gollum-editor-preview').length );
385
+ },
386
+
387
+
388
+ /**
389
+ * EditorHas.titleDisplayed
390
+ * True if the editor is displaying a title field, false otherwise.
391
+ *
392
+ * @return boolean
393
+ */
394
+ titleDisplayed: function() {
395
+ return ( ActiveOptions.NewFile );
396
+ }
397
+
398
+ };
399
+
400
+
401
+ /**
402
+ * FunctionBar
403
+ *
404
+ * Things the function bar does.
405
+ */
406
+ var FunctionBar = {
407
+
408
+ isActive: false,
409
+
410
+
411
+ /**
412
+ * FunctionBar.activate
413
+ * Activates the function bar, attaching all click events
414
+ * and displaying the bar.
415
+ *
416
+ */
417
+ activate: function() {
418
+ debug('Activating function bar');
419
+
420
+ // check these out
421
+ $('#gollum-editor-function-bar a.function-button').each(function() {
422
+ if ( LanguageDefinition.getDefinitionFor( $(this).attr('id') ) ) {
423
+ $(this).click( FunctionBar.evtFunctionButtonClick );
424
+ $(this).removeClass('disabled');
425
+ }
426
+ else if ( $(this).attr('id') != 'function-help' ) {
427
+ $(this).addClass('disabled');
428
+ }
429
+ });
430
+
431
+ // show bar as active
432
+ $('#gollum-editor-function-bar').addClass( 'active' );
433
+ FunctionBar.isActive = true;
434
+ },
435
+
436
+
437
+ deactivate: function() {
438
+ $('#gollum-editor-function-bar a.function-button').unbind('click');
439
+ $('#gollum-editor-function-bar').removeClass( 'active' );
440
+ FunctionBar.isActive = false;
441
+ },
442
+
443
+
444
+ /**
445
+ * FunctionBar.evtFunctionButtonClick
446
+ * Event handler for the function buttons. Traps the click and
447
+ * executes the proper language action.
448
+ *
449
+ * @param jQuery.Event jQuery event object.
450
+ */
451
+ evtFunctionButtonClick: function(e) {
452
+ e.preventDefault();
453
+ var def = LanguageDefinition.getDefinitionFor( $(this).attr('id') );
454
+ if ( typeof def == 'object' ) {
455
+ FunctionBar.executeAction( def );
456
+ }
457
+ },
458
+
459
+
460
+ /**
461
+ * FunctionBar.executeAction
462
+ * Executes a language-specific defined action for a function button.
463
+ *
464
+ */
465
+ executeAction: function( definitionObject ) {
466
+ // get the selected text from the textarea
467
+ var txt = $('#gollum-editor-body').val();
468
+ // hmm, I'm not sure this will work in a textarea
469
+ var selPos = FunctionBar
470
+ .getFieldSelectionPosition( $('#gollum-editor-body') );
471
+ var selText = FunctionBar.getFieldSelection( $('#gollum-editor-body') );
472
+ var repText = selText;
473
+ var reselect = true;
474
+ var cursor = null;
475
+
476
+ // execute a replacement function if one exists
477
+ if ( definitionObject.exec &&
478
+ typeof definitionObject.exec == 'function' ) {
479
+ definitionObject.exec( txt, selText, $('#gollum-editor-body') );
480
+ return;
481
+ }
482
+
483
+ // execute a search/replace if they exist
484
+ var searchExp = /([^\n]+)/gi;
485
+ if ( definitionObject.search &&
486
+ typeof definitionObject.search == 'object' ) {
487
+ debug('Replacing search Regex');
488
+ searchExp = null;
489
+ searchExp = new RegExp ( definitionObject.search );
490
+ debug( searchExp );
491
+ }
492
+ debug('repText is ' + '"' + repText + '"');
493
+ // replace text
494
+ if ( definitionObject.replace &&
495
+ typeof definitionObject.replace == 'string' ) {
496
+ debug('Running replacement - using ' + definitionObject.replace);
497
+ var rt = definitionObject.replace;
498
+ repText = repText.replace( searchExp, rt );
499
+ // remove backreferences
500
+ repText = repText.replace( /\$[\d]/g, '' );
501
+
502
+ if ( repText === '' ) {
503
+ debug('Search string is empty');
504
+
505
+ // find position of $1 - this is where we will place the cursor
506
+ cursor = rt.indexOf('$1');
507
+
508
+ // we have an empty string, so just remove backreferences
509
+ repText = rt.replace( /\$[\d]/g, '' );
510
+
511
+ // if the position of $1 doesn't exist, stick the cursor in
512
+ // the middle
513
+ if ( cursor == -1 ) {
514
+ cursor = Math.floor( rt.length / 2 );
515
+ }
516
+ }
517
+ }
518
+
519
+ // append if necessary
520
+ if ( definitionObject.append &&
521
+ typeof definitionObject.append == 'string' ) {
522
+ if ( repText == selText ) {
523
+ reselect = false;
524
+ }
525
+ repText += definitionObject.append;
526
+ }
527
+
528
+ if ( repText ) {
529
+ FunctionBar.replaceFieldSelection( $('#gollum-editor-body'),
530
+ repText, reselect, cursor );
531
+ }
532
+
533
+ },
534
+
535
+
536
+ /**
537
+ * getFieldSelectionPosition
538
+ * Retrieves the selection range for the textarea.
539
+ *
540
+ * @return object the .start and .end offsets in the string
541
+ */
542
+ getFieldSelectionPosition: function( $field ) {
543
+ if ($field.length) {
544
+ var start = 0, end = 0;
545
+ var el = $field.get(0);
546
+
547
+ if (typeof el.selectionStart == "number" &&
548
+ typeof el.selectionEnd == "number") {
549
+ start = el.selectionStart;
550
+ end = el.selectionEnd;
551
+ } else {
552
+ var range = document.selection.createRange();
553
+ var stored_range = range.duplicate();
554
+ stored_range.moveToElementText( el );
555
+ stored_range.setEndPoint( 'EndToEnd', range );
556
+ start = stored_range.text.length - range.text.length;
557
+ end = start + range.text.length;
558
+
559
+ // so, uh, we're close, but we need to search for line breaks and
560
+ // adjust the start/end points accordingly since IE counts them as
561
+ // 2 characters in TextRange.
562
+ var s = start;
563
+ var lb = 0;
564
+ var i;
565
+ debug('IE: start position is currently ' + s);
566
+ for ( i=0; i < s; i++ ) {
567
+ if ( el.value.charAt(i).match(/\r/) ) {
568
+ ++lb;
569
+ }
570
+ }
571
+
572
+ if ( lb ) {
573
+ debug('IE start: compensating for ' + lb + ' line breaks');
574
+ start = start - lb;
575
+ lb = 0;
576
+ }
577
+
578
+ var e = end;
579
+ for ( i=0; i < e; i++ ) {
580
+ if ( el.value.charAt(i).match(/\r/) ) {
581
+ ++lb;
582
+ }
583
+ }
584
+
585
+ if ( lb ) {
586
+ debug('IE end: compensating for ' + lb + ' line breaks');
587
+ end = end - lb;
588
+ }
589
+ }
590
+
591
+ return {
592
+ start: start,
593
+ end: end
594
+ };
595
+ } // end if ($field.length)
596
+ },
597
+
598
+
599
+ /**
600
+ * getFieldSelection
601
+ * Returns the currently selected substring of the textarea.
602
+ *
603
+ * @param jQuery A jQuery object for the textarea.
604
+ * @return string Selected string.
605
+ */
606
+ getFieldSelection: function( $field ) {
607
+ var selStr = '';
608
+ var selPos;
609
+
610
+ if ( $field.length ) {
611
+ selPos = FunctionBar.getFieldSelectionPosition( $field );
612
+ selStr = $field.val().substring( selPos.start, selPos.end );
613
+ debug('Selected: ' + selStr + ' (' + selPos.start + ', ' +
614
+ selPos.end + ')');
615
+ return selStr;
616
+ }
617
+ return false;
618
+ },
619
+
620
+
621
+ isShown: function() {
622
+ return ($('#gollum-editor-function-bar').is(':visible'));
623
+ },
624
+
625
+ refresh: function() {
626
+ if ( EditorHas.functionBar() ) {
627
+ debug('Refreshing function bar');
628
+ if ( LanguageDefinition.isValid() ) {
629
+ $('#gollum-editor-function-bar a.function-button').unbind('click');
630
+ FunctionBar.activate();
631
+ if ( Help ) {
632
+ Help.setActiveHelp( LanguageDefinition.getActiveLanguage() );
633
+ }
634
+ } else {
635
+ debug('Language definition is invalid.');
636
+ if ( FunctionBar.isShown() ) {
637
+ // deactivate the function bar; it's not gonna work now
638
+ FunctionBar.deactivate();
639
+ }
640
+ if ( Help.isShown() ) {
641
+ Help.hide();
642
+ }
643
+ }
644
+ }
645
+ },
646
+
647
+
648
+ /**
649
+ * replaceFieldSelection
650
+ * Replaces the currently selected substring of the textarea with
651
+ * a new string.
652
+ *
653
+ * @param jQuery A jQuery object for the textarea.
654
+ * @param string The string to replace the current selection with.
655
+ * @param boolean Reselect the new text range.
656
+ */
657
+ replaceFieldSelection: function( $field, replaceText, reselect, cursorOffset ) {
658
+ var selPos = FunctionBar.getFieldSelectionPosition( $field );
659
+ var fullStr = $field.val();
660
+ var selectNew = true;
661
+ if ( reselect === false) {
662
+ selectNew = false;
663
+ }
664
+
665
+ var scrollTop = null;
666
+ if ( $field[0].scrollTop ) {
667
+ scrollTop = $field[0].scrollTop;
668
+ }
669
+
670
+ $field.val( fullStr.substring(0, selPos.start) + replaceText +
671
+ fullStr.substring(selPos.end) );
672
+ $field[0].focus();
673
+
674
+ if ( selectNew ) {
675
+ if ( $field[0].setSelectionRange ) {
676
+ if ( cursorOffset ) {
677
+ $field[0].setSelectionRange(
678
+ selPos.start + cursorOffset,
679
+ selPos.start + cursorOffset
680
+ );
681
+ } else {
682
+ $field[0].setSelectionRange( selPos.start,
683
+ selPos.start + replaceText.length );
684
+ }
685
+ } else if ( $field[0].createTextRange ) {
686
+ var range = $field[0].createTextRange();
687
+ range.collapse( true );
688
+ if ( cursorOffset ) {
689
+ range.moveEnd( selPos.start + cursorOffset );
690
+ range.moveStart( selPos.start + cursorOffset );
691
+ } else {
692
+ range.moveEnd( 'character', selPos.start + replaceText.length );
693
+ range.moveStart( 'character', selPos.start );
694
+ }
695
+ range.select();
696
+ }
697
+ }
698
+
699
+ if ( scrollTop ) {
700
+ // this jumps sometimes in FF
701
+ $field[0].scrollTop = scrollTop;
702
+ }
703
+ }
704
+ };
705
+
706
+
707
+
708
+ /**
709
+ * FormatSelector
710
+ *
711
+ * Functions relating to the format selector (if it exists)
712
+ */
713
+ var FormatSelector = {
714
+
715
+ $_SELECTOR: null,
716
+
717
+ /**
718
+ * FormatSelector.evtChangeFormat
719
+ * Event handler for when a format has been changed by the format
720
+ * selector. Will automatically load a new language definition
721
+ * via JS if necessary.
722
+ *
723
+ * @return void
724
+ */
725
+ evtChangeFormat: function( e ) {
726
+ var newMarkup = $(this).val();
727
+ LanguageDefinition.setActiveLanguage( newMarkup );
728
+ },
729
+
730
+
731
+ /**
732
+ * FormatSelector.init
733
+ * Initializes the format selector.
734
+ *
735
+ * @return void
736
+ */
737
+ init: function( $sel ) {
738
+ debug('Initializing format selector');
739
+
740
+ // unbind events if init is being called twice for some reason
741
+ if ( FormatSelector.$_SELECTOR &&
742
+ typeof FormatSelector.$_SELECTOR == 'object' ) {
743
+ FormatSelector.$_SELECTOR.unbind( 'change' );
744
+ }
745
+
746
+ FormatSelector.$_SELECTOR = $sel;
747
+
748
+ // set format selector to the current language
749
+ FormatSelector.updateSelected();
750
+ FormatSelector.$_SELECTOR.change( FormatSelector.evtChangeFormat );
751
+ },
752
+
753
+
754
+ /**
755
+ * FormatSelector.update
756
+ */
757
+ updateSelected: function() {
758
+ var currentLang = LanguageDefinition.getActiveLanguage();
759
+ FormatSelector.$_SELECTOR.val( currentLang );
760
+ }
761
+
762
+ };
763
+
764
+
765
+
766
+ /**
767
+ * Help
768
+ *
769
+ * Functions that manage the display and loading of inline help files.
770
+ */
771
+ var Help = {
772
+
773
+ _ACTIVE_HELP: '',
774
+ _LOADED_HELP_LANGS: [],
775
+ _HELP: {},
776
+
777
+ /**
778
+ * Help.define
779
+ *
780
+ * Defines a new help context and enables the help function if it
781
+ * exists in the Gollum Function Bar.
782
+ *
783
+ * @param string name The name you're giving to this help context.
784
+ * Generally, this should match the language name.
785
+ * @param object definitionObject The definition object being loaded from a
786
+ * language / help definition file.
787
+ * @return void
788
+ */
789
+ define: function( name, definitionObject ) {
790
+ if ( Help.isValidHelpFormat( definitionObject ) ) {
791
+ debug('help is a valid format');
792
+
793
+ Help._ACTIVE_HELP_LANG = name;
794
+ Help._LOADED_HELP_LANGS.push( name );
795
+ Help._HELP[name] = definitionObject;
796
+
797
+ if ( $("#function-help").length ) {
798
+ if ( $('#function-help').hasClass('disabled') ) {
799
+ $('#function-help').removeClass('disabled');
800
+ }
801
+ $('#function-help').unbind('click');
802
+ $('#function-help').click( Help.evtHelpButtonClick );
803
+
804
+ // generate help menus
805
+ Help.generateHelpMenuFor( name );
806
+
807
+ if ( $('#gollum-editor-help').length &&
808
+ typeof $('#gollum-editor-help').attr('data-autodisplay') !== 'undefined' &&
809
+ $('#gollum-editor-help').attr('data-autodisplay') === 'true' ) {
810
+ Help.show();
811
+ }
812
+ }
813
+ } else {
814
+ if ( $('#function-help').length ) {
815
+ $('#function-help').addClass('disabled');
816
+ }
817
+ }
818
+ },
819
+
820
+ /**
821
+ * Help.generateHelpMenuFor
822
+ * Generates the markup for the main help menu given a context name.
823
+ *
824
+ * @param string name The context name.
825
+ * @return void
826
+ */
827
+ generateHelpMenuFor: function( name ) {
828
+ if ( !Help._HELP[name] ) {
829
+ debug('Help is not defined for ' + name.toString());
830
+ return false;
831
+ }
832
+ var helpData = Help._HELP[name];
833
+
834
+ // clear this shiz out
835
+ $('#gollum-editor-help-parent').html('');
836
+ $('#gollum-editor-help-list').html('');
837
+ $('#gollum-editor-help-content').html('');
838
+
839
+ // go go inefficient algorithm
840
+ for ( var i=0; i < helpData.length; i++ ) {
841
+ if ( typeof helpData[i] != 'object' ) {
842
+ break;
843
+ }
844
+
845
+ var $newLi = $('<li><a href="#" rel="' + i + '">' +
846
+ helpData[i].menuName + '</a></li>');
847
+ $('#gollum-editor-help-parent').append( $newLi );
848
+ if ( i === 0 ) {
849
+ // select on first run
850
+ $newLi.children('a').addClass('selected');
851
+ }
852
+ $newLi.children('a').click( Help.evtParentMenuClick );
853
+ }
854
+
855
+ // generate parent submenu on first run
856
+ Help.generateSubMenu( helpData[0], 0 );
857
+ $($('#gollum-editor-help-list li a').get(0)).click();
858
+
859
+ },
860
+
861
+ /**
862
+ * Help.generateSubMenu
863
+ * Generates the markup for the inline help sub-menu given the data
864
+ * object for the submenu and the array index to start at.
865
+ *
866
+ * @param object subData The data for the sub-menu.
867
+ * @param integer index The index clicked on (parent menu index).
868
+ * @return void
869
+ */
870
+ generateSubMenu: function( subData, index ) {
871
+ $('#gollum-editor-help-list').html('');
872
+ $('#gollum-editor-help-content').html('');
873
+ for ( var i=0; i < subData.content.length; i++ ) {
874
+ if ( typeof subData.content[i] != 'object' ) {
875
+ break;
876
+ }
877
+
878
+ var $subLi = $('<li><a href="#" rel="' + index + ':' + i + '">' +
879
+ subData.content[i].menuName + '</a></li>');
880
+
881
+
882
+ $('#gollum-editor-help-list').append( $subLi );
883
+ $subLi.children('a').click( Help.evtSubMenuClick );
884
+ }
885
+ },
886
+
887
+ hide: function() {
888
+ if ( $.browser.msie ) {
889
+ $('#gollum-editor-help').css('display', 'none');
890
+ } else {
891
+ $('#gollum-editor-help').animate({
892
+ opacity: 0
893
+ }, 200, function() {
894
+ $('#gollum-editor-help')
895
+ .animate({ height: 'hide' }, 200);
896
+ });
897
+ }
898
+ },
899
+
900
+ show: function() {
901
+ if ( $.browser.msie ) {
902
+ // bypass effects for internet explorer, since it does weird crap
903
+ // to text antialiasing with opacity animations
904
+ $('#gollum-editor-help').css('display', 'block');
905
+ } else {
906
+ $('#gollum-editor-help').animate({
907
+ height: 'show'
908
+ }, 200, function() {
909
+ $('#gollum-editor-help')
910
+ .animate({ opacity: 1 }, 300);
911
+ });
912
+ }
913
+ },
914
+
915
+ /**
916
+ * Help.showHelpFor
917
+ * Displays the actual help content given the two menu indexes, which are
918
+ * rendered in the rel="" attributes of the help menus
919
+ *
920
+ * @param integer index1 parent index
921
+ * @param integer index2 submenu index
922
+ * @return void
923
+ */
924
+ showHelpFor: function( index1, index2 ) {
925
+ var html =
926
+ Help._HELP[Help._ACTIVE_HELP_LANG][index1].content[index2].data;
927
+ $('#gollum-editor-help-content').html(html);
928
+ },
929
+
930
+ /**
931
+ * Help.isLoadedFor
932
+ * Returns true if help is loaded for a specific markup language,
933
+ * false otherwise.
934
+ *
935
+ * @param string name The name of the markup language.
936
+ * @return boolean
937
+ */
938
+ isLoadedFor: function( name ) {
939
+ for ( var i=0; i < Help._LOADED_HELP_LANGS.length; i++ ) {
940
+ if ( name == Help._LOADED_HELP_LANGS[i] ) {
941
+ return true;
942
+ }
943
+ }
944
+ return false;
945
+ },
946
+
947
+ isShown: function() {
948
+ return ($('#gollum-editor-help').is(':visible'));
949
+ },
950
+
951
+ /**
952
+ * Help.isValidHelpFormat
953
+ * Does a quick check to make sure that the help definition isn't in a
954
+ * completely messed-up format.
955
+ *
956
+ * @param object (Array) helpArr The help definition array.
957
+ * @return boolean
958
+ */
959
+ isValidHelpFormat: function( helpArr ) {
960
+ return ( typeof helpArr == 'object' &&
961
+ helpArr.length &&
962
+ typeof helpArr[0].menuName == 'string' &&
963
+ typeof helpArr[0].content == 'object' &&
964
+ helpArr[0].content.length );
965
+ },
966
+
967
+ /**
968
+ * Help.setActiveHelp
969
+ * Sets the active help definition to the one defined in the argument,
970
+ * re-rendering the help menu to match the new definition.
971
+ *
972
+ * @param string name The name of the help definition.
973
+ * @return void
974
+ */
975
+ setActiveHelp: function( name ) {
976
+ if ( !Help.isLoadedFor( name ) ) {
977
+ if ( $('#function-help').length ) {
978
+ $('#function-help').addClass('disabled');
979
+ }
980
+ if ( Help.isShown() ) {
981
+ Help.hide();
982
+ }
983
+ } else {
984
+ Help._ACTIVE_HELP_LANG = name;
985
+ if ( $("#function-help").length ) {
986
+ if ( $('#function-help').hasClass('disabled') ) {
987
+ $('#function-help').removeClass('disabled');
988
+ }
989
+ $('#function-help').unbind('click');
990
+ $('#function-help').click( Help.evtHelpButtonClick );
991
+ Help.generateHelpMenuFor( name );
992
+ }
993
+ }
994
+ },
995
+
996
+ /**
997
+ * Help.evtHelpButtonClick
998
+ * Event handler for clicking the help button in the function bar.
999
+ *
1000
+ * @param jQuery.Event e The jQuery event object.
1001
+ * @return void
1002
+ */
1003
+ evtHelpButtonClick: function( e ) {
1004
+ e.preventDefault();
1005
+ if ( Help.isShown() ) {
1006
+ // turn off autodisplay if it's on
1007
+ if ( $('#gollum-editor-help').length &&
1008
+ $('#gollum-editor-help').attr('data-autodisplay') !== 'undefined' &&
1009
+ $('#gollum-editor-help').attr('data-autodisplay') === 'true' ) {
1010
+ $.post('/wiki/help?_method=delete');
1011
+ $('#gollum-editor-help').attr('data-autodisplay', '');
1012
+ }
1013
+ Help.hide(); }
1014
+ else { Help.show(); }
1015
+ },
1016
+
1017
+ /**
1018
+ * Help.evtParentMenuClick
1019
+ * Event handler for clicking on an item in the parent menu. Automatically
1020
+ * renders the submenu for the parent menu as well as the first result for
1021
+ * the actual plain text.
1022
+ *
1023
+ * @param jQuery.Event e The jQuery event object.
1024
+ * @return void
1025
+ */
1026
+ evtParentMenuClick: function( e ) {
1027
+ e.preventDefault();
1028
+ // short circuit if we've selected this already
1029
+ if ( $(this).hasClass('selected') ) { return; }
1030
+
1031
+ // populate from help data for this
1032
+ var helpIndex = $(this).attr('rel');
1033
+ var subData = Help._HELP[Help._ACTIVE_HELP_LANG][helpIndex];
1034
+
1035
+ $('#gollum-editor-help-parent li a').removeClass('selected');
1036
+ $(this).addClass('selected');
1037
+ Help.generateSubMenu( subData, helpIndex );
1038
+ $($('#gollum-editor-help-list li a').get(0)).click();
1039
+ },
1040
+
1041
+ /**
1042
+ * Help.evtSubMenuClick
1043
+ * Event handler for clicking an item in a help submenu. Renders the
1044
+ * appropriate text for the submenu link.
1045
+ *
1046
+ * @param jQuery.Event e The jQuery event object.
1047
+ * @return void
1048
+ */
1049
+ evtSubMenuClick: function( e ) {
1050
+ e.preventDefault();
1051
+ if ( $(this).hasClass('selected') ) { return; }
1052
+
1053
+ // split index rel data
1054
+ var rawIndex = $(this).attr('rel').split(':');
1055
+ $('#gollum-editor-help-list li a').removeClass('selected');
1056
+ $(this).addClass('selected');
1057
+ Help.showHelpFor( rawIndex[0], rawIndex[1] );
1058
+ }
1059
+ };
1060
+
1061
+ // Publicly-accessible function to Help.define
1062
+ $.GollumEditor.defineHelp = Help.define;
1063
+
1064
+ // Dialog exists as its own thing now
1065
+ $.GollumEditor.Dialog = $.GollumDialog;
1066
+ $.GollumEditor.replaceSelection = function( repText ) {
1067
+ FunctionBar.replaceFieldSelection( $('#gollum-editor-body'), repText );
1068
+ };
1069
+
1070
+ // Placeholder exists as its own thing now
1071
+ $.GollumEditor.Placeholder = $.GollumPlaceholder;
1072
+
1073
+ })(jQuery);