wheels 0.0.48 → 0.0.49

Sign up to get free protection for your applications and to get access to all the features.
Files changed (215) hide show
  1. data/VERSION +1 -1
  2. data/app/controllers/access_control_entries_controller.rb +4 -4
  3. data/app/controllers/external_links_controller.rb +5 -0
  4. data/app/controllers/feedbacks_controller.rb +10 -0
  5. data/app/controllers/menus_controller.rb +2 -0
  6. data/app/controllers/pages_controller.rb +16 -29
  7. data/app/controllers/sitemaps_controller.rb +135 -0
  8. data/app/helpers/application_helper.rb +4 -3
  9. data/app/helpers/external_links_helper.rb +2 -0
  10. data/app/helpers/feedbacks_helper.rb +2 -0
  11. data/app/helpers/menus_helper.rb +2 -0
  12. data/app/helpers/sitemaps_helper.rb +12 -0
  13. data/app/mailers/feedback_mailer.rb +10 -0
  14. data/app/models/ability.rb +2 -1
  15. data/app/models/access_control_entry.rb +17 -15
  16. data/app/models/external_link.rb +4 -0
  17. data/app/models/feedback.rb +13 -0
  18. data/app/models/image.rb +1 -1
  19. data/app/models/menu.rb +4 -0
  20. data/app/models/page.rb +2 -5
  21. data/app/models/sitemap.rb +153 -0
  22. data/app/models/user.rb +7 -1
  23. data/app/validators/email_validator.rb +22 -0
  24. data/app/views/access_control_entries/_form.html.haml +1 -1
  25. data/app/views/access_control_entries/_index.html.haml +3 -3
  26. data/app/views/access_control_entries/_show.html.haml +1 -1
  27. data/app/views/external_links/_fields_for.html.haml +2 -0
  28. data/app/views/external_links/_form.html.haml +18 -0
  29. data/app/views/external_links/_show.html.haml +7 -0
  30. data/app/views/external_links/edit.html.haml +7 -0
  31. data/app/views/external_links/index.html.haml +23 -0
  32. data/app/views/external_links/new.html.haml +5 -0
  33. data/app/views/external_links/show.html.haml +2 -0
  34. data/app/views/feedback_mailer/submit_feedback.html.haml +22 -0
  35. data/app/views/feedbacks/_form.html.haml +37 -0
  36. data/app/views/feedbacks/index.html.haml +27 -0
  37. data/app/views/feedbacks/new.html.haml +5 -0
  38. data/app/views/feedbacks/show.html.haml +19 -0
  39. data/app/views/layouts/application.html.haml +21 -16
  40. data/app/views/layouts/bare.html.haml +2 -0
  41. data/app/views/loadbehind/_view.js.haml +1 -2
  42. data/app/views/menus/_form.html.haml +13 -0
  43. data/app/views/menus/edit.html.haml +7 -0
  44. data/app/views/menus/index.html.haml +19 -0
  45. data/app/views/menus/new.html.haml +5 -0
  46. data/app/views/menus/show.html.haml +7 -0
  47. data/app/views/pages/_child_pages_links.html.haml +1 -1
  48. data/app/views/pages/_control_panel.html.haml +1 -6
  49. data/app/views/pages/_form.html.haml +2 -2
  50. data/app/views/pages/_form_fields.html.haml +7 -2
  51. data/app/views/pages/_show.html.haml +4 -0
  52. data/app/views/pages/create.js.haml +2 -1
  53. data/app/views/pages/destroy.js.haml +3 -0
  54. data/app/views/pages/edit.js.haml +4 -0
  55. data/app/views/pages/index.html.haml +4 -2
  56. data/app/views/pages/index.js.haml +3 -0
  57. data/app/views/pages/new.js.haml +3 -0
  58. data/app/views/pages/show.html.haml +2 -10
  59. data/app/views/pages/show.js.haml +3 -0
  60. data/app/views/pages/update.js.haml +2 -2
  61. data/app/views/sitemaps/edit.html.haml +12 -0
  62. data/app/views/sitemaps/edit.js.erb +0 -0
  63. data/app/views/sitemaps/index.html.haml +93 -0
  64. data/app/views/sitemaps/index.json.erb +23 -0
  65. data/app/views/sitemaps/new.html.haml +8 -0
  66. data/app/views/sitemaps/new.js.erb +0 -0
  67. data/app/views/users/edit.html.haml +45 -0
  68. data/db/migrate/{add_fields_to_users.rb → 0010_add_fields_to_users.rb} +0 -0
  69. data/db/migrate/{create_blogs.rb → 0020_create_blogs.rb} +0 -0
  70. data/db/migrate/{create_galleries.rb → 0030_create_galleries.rb} +0 -0
  71. data/db/migrate/{create_images.rb → 0040_create_images.rb} +0 -0
  72. data/db/migrate/{create_profiles.rb → 0050_create_profiles.rb} +0 -0
  73. data/db/migrate/{insert_admin_user_and_roles.rb → 0060_insert_admin_user_and_roles.rb} +0 -0
  74. data/db/migrate/{create_pages.rb → 0070_create_pages.rb} +0 -0
  75. data/db/migrate/{create_forums.rb → 0080_create_forums.rb} +0 -0
  76. data/db/migrate/{create_discussions.rb → 0090_create_discussions.rb} +0 -0
  77. data/db/migrate/{create_forum_messages.rb → 0100_create_forum_messages.rb} +0 -0
  78. data/db/migrate/{create_access_control_entries.rb → 0110_create_access_control_entries.rb} +3 -3
  79. data/db/migrate/{create_attachments.rb → 0120_create_attachments.rb} +0 -4
  80. data/db/migrate/{create_roles.rb → 0130_create_roles.rb} +0 -0
  81. data/db/migrate/0140_create_feedbacks.rb +20 -0
  82. data/db/migrate/0150_create_external_links.rb +14 -0
  83. data/db/migrate/0160_create_sitemaps.rb +17 -0
  84. data/db/migrate/0170_create_menus.rb +14 -0
  85. data/lib/development_mail_interceptor.rb +7 -0
  86. data/lib/generators/wheels/recipes/wheels.rb +18 -12
  87. data/lib/wheels/base.rb +7 -0
  88. data/lib/wheels/routes.rb +8 -3
  89. data/lib/wheels.rb +2 -0
  90. data/public/javascripts/jquery-validate/additional-methods.js +259 -0
  91. data/public/javascripts/jquery-validate/changelog.txt +239 -0
  92. data/public/javascripts/jquery-validate/jquery.validate.js +1146 -0
  93. data/public/javascripts/jquery-validate/jquery.validate.min.js +16 -0
  94. data/public/javascripts/jquery-validate/jquery.validate.pack.js +15 -0
  95. data/public/javascripts/jquery-validate/lib/jquery-1.4.2.js +6240 -0
  96. data/public/javascripts/jquery-validate/lib/jquery.form.js +660 -0
  97. data/public/javascripts/jquery-validate/lib/jquery.js +4376 -0
  98. data/public/javascripts/jquery-validate/lib/jquery.metadata.js +122 -0
  99. data/public/javascripts/jquery-validate/localization/messages_ar.js +24 -0
  100. data/public/javascripts/jquery-validate/localization/messages_bg.js +23 -0
  101. data/public/javascripts/jquery-validate/localization/messages_cn.js +23 -0
  102. data/public/javascripts/jquery-validate/localization/messages_cs.js +23 -0
  103. data/public/javascripts/jquery-validate/localization/messages_da.js +20 -0
  104. data/public/javascripts/jquery-validate/localization/messages_de.js +20 -0
  105. data/public/javascripts/jquery-validate/localization/messages_el.js +24 -0
  106. data/public/javascripts/jquery-validate/localization/messages_es.js +23 -0
  107. data/public/javascripts/jquery-validate/localization/messages_fa.js +23 -0
  108. data/public/javascripts/jquery-validate/localization/messages_fi.js +21 -0
  109. data/public/javascripts/jquery-validate/localization/messages_fr.js +23 -0
  110. data/public/javascripts/jquery-validate/localization/messages_he.js +23 -0
  111. data/public/javascripts/jquery-validate/localization/messages_hu.js +20 -0
  112. data/public/javascripts/jquery-validate/localization/messages_it.js +23 -0
  113. data/public/javascripts/jquery-validate/localization/messages_kk.js +23 -0
  114. data/public/javascripts/jquery-validate/localization/messages_lt.js +23 -0
  115. data/public/javascripts/jquery-validate/localization/messages_lv.js +23 -0
  116. data/public/javascripts/jquery-validate/localization/messages_nl.js +23 -0
  117. data/public/javascripts/jquery-validate/localization/messages_no.js +23 -0
  118. data/public/javascripts/jquery-validate/localization/messages_pl.js +23 -0
  119. data/public/javascripts/jquery-validate/localization/messages_ptbr.js +23 -0
  120. data/public/javascripts/jquery-validate/localization/messages_ptpt.js +23 -0
  121. data/public/javascripts/jquery-validate/localization/messages_ro.js +23 -0
  122. data/public/javascripts/jquery-validate/localization/messages_ru.js +23 -0
  123. data/public/javascripts/jquery-validate/localization/messages_se.js +21 -0
  124. data/public/javascripts/jquery-validate/localization/messages_sk.js +20 -0
  125. data/public/javascripts/jquery-validate/localization/messages_tr.js +23 -0
  126. data/public/javascripts/jquery-validate/localization/messages_tw.js +23 -0
  127. data/public/javascripts/jquery-validate/localization/messages_ua.js +23 -0
  128. data/public/javascripts/jquery-validate/localization/methods_de.js +12 -0
  129. data/public/javascripts/jquery-validate/localization/methods_nl.js +9 -0
  130. data/public/javascripts/jquery-validate/localization/methods_pt.js +9 -0
  131. data/public/javascripts/jquery-validate/todo +172 -0
  132. data/public/javascripts/jquery.cookie.js +96 -0
  133. data/public/javascripts/jquery.filedrop.js +253 -0
  134. data/public/javascripts/jquery.hotkeys.js +99 -0
  135. data/public/javascripts/jquery.js +6240 -0
  136. data/public/javascripts/jquery.jstree.js +3510 -0
  137. data/public/javascripts/jquery.uploadify.js +26 -0
  138. data/public/javascripts/jquery.validate.js +1147 -0
  139. data/public/javascripts/sitemap_jstree.js +329 -0
  140. data/public/javascripts/swfobject.js +4 -0
  141. data/public/jstree/_demo/_dump.sql +20 -0
  142. data/public/jstree/_demo/_inc/__mysql_errors.log +0 -0
  143. data/public/jstree/_demo/_inc/class._database.php +146 -0
  144. data/public/jstree/_demo/_inc/class._database_i.php +152 -0
  145. data/public/jstree/_demo/_inc/class.tree.php +602 -0
  146. data/public/jstree/_demo/_install.txt +6 -0
  147. data/public/jstree/_demo/config.php +14 -0
  148. data/public/jstree/_demo/index.html +262 -0
  149. data/public/jstree/_demo/server.php +69 -0
  150. data/public/jstree/_docs/!style.css +37 -0
  151. data/public/jstree/_docs/_drive.png +0 -0
  152. data/public/jstree/_docs/_html_data.html +2 -0
  153. data/public/jstree/_docs/_json_data.json +4 -0
  154. data/public/jstree/_docs/_search_data.json +6 -0
  155. data/public/jstree/_docs/_search_result.json +1 -0
  156. data/public/jstree/_docs/_xml_flat.xml +12 -0
  157. data/public/jstree/_docs/_xml_nest.xml +18 -0
  158. data/public/jstree/_docs/checkbox.html +148 -0
  159. data/public/jstree/_docs/contextmenu.html +120 -0
  160. data/public/jstree/_docs/cookies.html +96 -0
  161. data/public/jstree/_docs/core.html +622 -0
  162. data/public/jstree/_docs/crrm.html +315 -0
  163. data/public/jstree/_docs/dnd.html +197 -0
  164. data/public/jstree/_docs/hotkeys.html +81 -0
  165. data/public/jstree/_docs/html_data.html +174 -0
  166. data/public/jstree/_docs/index.html +75 -0
  167. data/public/jstree/_docs/json_data.html +240 -0
  168. data/public/jstree/_docs/languages.html +138 -0
  169. data/public/jstree/_docs/search.html +114 -0
  170. data/public/jstree/_docs/sort.html +84 -0
  171. data/public/jstree/_docs/syntax/!script.js +2232 -0
  172. data/public/jstree/_docs/syntax/!style.css +511 -0
  173. data/public/jstree/_docs/syntax/clipboard.swf +0 -0
  174. data/public/jstree/_docs/syntax/help.png +0 -0
  175. data/public/jstree/_docs/syntax/magnifier.png +0 -0
  176. data/public/jstree/_docs/syntax/page_white_code.png +0 -0
  177. data/public/jstree/_docs/syntax/page_white_copy.png +0 -0
  178. data/public/jstree/_docs/syntax/printer.png +0 -0
  179. data/public/jstree/_docs/syntax/wrapping.png +0 -0
  180. data/public/jstree/_docs/themeroller.html +98 -0
  181. data/public/jstree/_docs/themes.html +126 -0
  182. data/public/jstree/_docs/types.html +173 -0
  183. data/public/jstree/_docs/ui.html +188 -0
  184. data/public/jstree/_docs/unique.html +70 -0
  185. data/public/jstree/_docs/xml_data.html +214 -0
  186. data/public/jstree/_lib/jquery.cookie.js +96 -0
  187. data/public/jstree/_lib/jquery.hotkeys.js +99 -0
  188. data/public/jstree/_lib/jquery.js +6240 -0
  189. data/public/jstree/jquery.jstree.js +3510 -0
  190. data/public/jstree/jstree.html +237 -0
  191. data/public/jstree/themes/apple/bg.jpg +0 -0
  192. data/public/jstree/themes/apple/d.png +0 -0
  193. data/public/jstree/themes/apple/dot_for_ie.gif +0 -0
  194. data/public/jstree/themes/apple/style.css +60 -0
  195. data/public/jstree/themes/apple/throbber.gif +0 -0
  196. data/public/jstree/themes/classic/d.png +0 -0
  197. data/public/jstree/themes/classic/dot_for_ie.gif +0 -0
  198. data/public/jstree/themes/classic/style.css +59 -0
  199. data/public/jstree/themes/classic/throbber.gif +0 -0
  200. data/public/jstree/themes/default/d.gif +0 -0
  201. data/public/jstree/themes/default/d.png +0 -0
  202. data/public/jstree/themes/default/style.css +73 -0
  203. data/public/jstree/themes/default/throbber.gif +0 -0
  204. data/public/jstree/themes/default-rtl/d.gif +0 -0
  205. data/public/jstree/themes/default-rtl/d.png +0 -0
  206. data/public/jstree/themes/default-rtl/dots.gif +0 -0
  207. data/public/jstree/themes/default-rtl/style.css +83 -0
  208. data/public/jstree/themes/default-rtl/throbber.gif +0 -0
  209. data/public/stylesheets/sass/dreamy.sass +21 -56
  210. data/public/stylesheets/sass/menu.sass +43 -9
  211. data/public/stylesheets/sass/uploadify.sass +52 -0
  212. data/public/stylesheets/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  213. data/public/stylesheets/ui-lightness/jquery-ui-1.8.4.custom.css +549 -0
  214. data/wheels.gemspec +187 -15
  215. metadata +188 -16
@@ -0,0 +1,2232 @@
1
+ /**
2
+ * SyntaxHighlighter
3
+ * http://alexgorbatchev.com/
4
+ *
5
+ * SyntaxHighlighter is donationware. If you are using it, please donate.
6
+ * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate
7
+ *
8
+ * @version
9
+ * 2.1.364 (October 15 2009)
10
+ *
11
+ * @copyright
12
+ * Copyright (C) 2004-2009 Alex Gorbatchev.
13
+ *
14
+ * @license
15
+ * This file is part of SyntaxHighlighter.
16
+ *
17
+ * SyntaxHighlighter is free software: you can redistribute it and/or modify
18
+ * it under the terms of the GNU Lesser General Public License as published by
19
+ * the Free Software Foundation, either version 3 of the License, or
20
+ * (at your option) any later version.
21
+ *
22
+ * SyntaxHighlighter is distributed in the hope that it will be useful,
23
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
+ * GNU General Public License for more details.
26
+ *
27
+ * You should have received a copy of the GNU General Public License
28
+ * along with SyntaxHighlighter. If not, see <http://www.gnu.org/copyleft/lesser.html>.
29
+ */
30
+ //
31
+ // Begin anonymous function. This is used to contain local scope variables without polutting global scope.
32
+ //
33
+ if (!window.SyntaxHighlighter) var SyntaxHighlighter = function() {
34
+
35
+ // Shortcut object which will be assigned to the SyntaxHighlighter variable.
36
+ // This is a shorthand for local reference in order to avoid long namespace
37
+ // references to SyntaxHighlighter.whatever...
38
+ var sh = {
39
+ defaults : {
40
+ /** Additional CSS class names to be added to highlighter elements. */
41
+ 'class-name' : '',
42
+
43
+ /** First line number. */
44
+ 'first-line' : 1,
45
+
46
+ /**
47
+ * Pads line numbers. Possible values are:
48
+ *
49
+ * false - don't pad line numbers.
50
+ * true - automaticaly pad numbers with minimum required number of leading zeroes.
51
+ * [int] - length up to which pad line numbers.
52
+ */
53
+ 'pad-line-numbers' : true,
54
+
55
+ /** Lines to highlight. */
56
+ 'highlight' : null,
57
+
58
+ /** Enables or disables smart tabs. */
59
+ 'smart-tabs' : true,
60
+
61
+ /** Gets or sets tab size. */
62
+ 'tab-size' : 4,
63
+
64
+ /** Enables or disables gutter. */
65
+ 'gutter' : true,
66
+
67
+ /** Enables or disables toolbar. */
68
+ 'toolbar' : true,
69
+
70
+ /** Forces code view to be collapsed. */
71
+ 'collapse' : false,
72
+
73
+ /** Enables or disables automatic links. */
74
+ 'auto-links' : true,
75
+
76
+ /** Gets or sets light mode. Equavalent to turning off gutter and toolbar. */
77
+ 'light' : false,
78
+
79
+ /** Enables or disables automatic line wrapping. */
80
+ 'wrap-lines' : true,
81
+
82
+ 'html-script' : false
83
+ },
84
+
85
+ config : {
86
+ /** Enables use of <SCRIPT type="syntaxhighlighter" /> tags. */
87
+ useScriptTags : true,
88
+
89
+ /** Path to the copy to clipboard SWF file. */
90
+ clipboardSwf : null,
91
+
92
+ /** Width of an item in the toolbar. */
93
+ toolbarItemWidth : 16,
94
+
95
+ /** Height of an item in the toolbar. */
96
+ toolbarItemHeight : 16,
97
+
98
+ /** Blogger mode flag. */
99
+ bloggerMode : false,
100
+
101
+ stripBrs : false,
102
+
103
+ /** Name of the tag that SyntaxHighlighter will automatically look for. */
104
+ tagName : 'pre',
105
+
106
+ strings : {
107
+ expandSource : 'show source',
108
+ viewSource : 'view source',
109
+ copyToClipboard : 'copy to clipboard',
110
+ copyToClipboardConfirmation : 'The code is in your clipboard now',
111
+ print : 'print',
112
+ help : '?',
113
+ alert: 'SyntaxHighlighter\n\n',
114
+ noBrush : 'Can\'t find brush for: ',
115
+ brushNotHtmlScript : 'Brush wasn\'t configured for html-script option: ',
116
+
117
+ // this is populated by the build script
118
+ aboutDialog : '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>About SyntaxHighlighter</title></head><body style="font-family:Geneva,Arial,Helvetica,sans-serif;background-color:#fff;color:#000;font-size:1em;text-align:center;"><div style="text-align:center;margin-top:3em;"><div style="font-size:xx-large;">SyntaxHighlighter</div><div style="font-size:.75em;margin-bottom:4em;"><div>version 2.1.364 (October 15 2009)</div><div><a href="http://alexgorbatchev.com" target="_blank" style="color:#0099FF;text-decoration:none;">http://alexgorbatchev.com</a></div><div>If you like this script, please <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=2930402" style="color:#0099FF;text-decoration:none;">donate</a> to keep development active!</div></div><div>JavaScript code syntax highlighter.</div><div>Copyright 2004-2009 Alex Gorbatchev.</div></div></body></html>'
119
+ },
120
+
121
+ /** If true, output will show HTML produces instead. */
122
+ debug : false
123
+ },
124
+
125
+ /** Internal 'global' variables. */
126
+ vars : {
127
+ discoveredBrushes : null,
128
+ spaceWidth : null,
129
+ printFrame : null,
130
+ highlighters : {}
131
+ },
132
+
133
+ /** This object is populated by user included external brush files. */
134
+ brushes : {},
135
+
136
+ /** Common regular expressions. */
137
+ regexLib : {
138
+ multiLineCComments : /\/\*[\s\S]*?\*\//gm,
139
+ singleLineCComments : /\/\/.*$/gm,
140
+ singleLinePerlComments : /#.*$/gm,
141
+ doubleQuotedString : /"([^\\"\n]|\\.)*"/g,
142
+ singleQuotedString : /'([^\\'\n]|\\.)*'/g,
143
+ multiLineDoubleQuotedString : /"([^\\"]|\\.)*"/g,
144
+ multiLineSingleQuotedString : /'([^\\']|\\.)*'/g,
145
+ xmlComments : /(&lt;|<)!--[\s\S]*?--(&gt;|>)/gm,
146
+ url : /&lt;\w+:\/\/[\w-.\/?%&=@:;]*&gt;|\w+:\/\/[\w-.\/?%&=@:;]*/g,
147
+
148
+ /** <?= ?> tags. */
149
+ phpScriptTags : { left: /(&lt;|<)\?=?/g, right: /\?(&gt;|>)/g },
150
+
151
+ /** <%= %> tags. */
152
+ aspScriptTags : { left: /(&lt;|<)%=?/g, right: /%(&gt;|>)/g },
153
+
154
+ /** <script></script> tags. */
155
+ scriptScriptTags : { left: /(&lt;|<)\s*script.*?(&gt;|>)/gi, right: /(&lt;|<)\/\s*script\s*(&gt;|>)/gi }
156
+ },
157
+
158
+ toolbar : {
159
+ /**
160
+ * Creates new toolbar for a highlighter.
161
+ * @param {Highlighter} highlighter Target highlighter.
162
+ */
163
+ create : function(highlighter)
164
+ {
165
+ var div = document.createElement('DIV'),
166
+ items = sh.toolbar.items
167
+ ;
168
+
169
+ div.className = 'toolbar';
170
+
171
+ for (var name in items)
172
+ {
173
+ var constructor = items[name],
174
+ command = new constructor(highlighter),
175
+ element = command.create()
176
+ ;
177
+
178
+ highlighter.toolbarCommands[name] = command;
179
+
180
+ if (element == null)
181
+ continue;
182
+
183
+ if (typeof(element) == 'string')
184
+ element = sh.toolbar.createButton(element, highlighter.id, name);
185
+
186
+ element.className += 'item ' + name;
187
+ div.appendChild(element);
188
+ }
189
+
190
+ return div;
191
+ },
192
+
193
+ /**
194
+ * Create a standard anchor button for the toolbar.
195
+ * @param {String} label Label text to display.
196
+ * @param {String} highlighterId Highlighter ID that this button would belong to.
197
+ * @param {String} commandName Command name that would be executed.
198
+ * @return {Element} Returns an 'A' element.
199
+ */
200
+ createButton : function(label, highlighterId, commandName)
201
+ {
202
+ var a = document.createElement('a'),
203
+ style = a.style,
204
+ config = sh.config,
205
+ width = config.toolbarItemWidth,
206
+ height = config.toolbarItemHeight
207
+ ;
208
+
209
+ a.href = '#' + commandName;
210
+ a.title = label;
211
+ a.highlighterId = highlighterId;
212
+ a.commandName = commandName;
213
+ a.innerHTML = label;
214
+
215
+ if (isNaN(width) == false)
216
+ style.width = width + 'px';
217
+
218
+ if (isNaN(height) == false)
219
+ style.height = height + 'px';
220
+
221
+ a.onclick = function(e)
222
+ {
223
+ try
224
+ {
225
+ sh.toolbar.executeCommand(
226
+ this,
227
+ e || window.event,
228
+ this.highlighterId,
229
+ this.commandName
230
+ );
231
+ }
232
+ catch(e)
233
+ {
234
+ sh.utils.alert(e.message);
235
+ }
236
+
237
+ return false;
238
+ };
239
+
240
+ return a;
241
+ },
242
+
243
+ /**
244
+ * Executes a toolbar command.
245
+ * @param {Element} sender Sender element.
246
+ * @param {MouseEvent} event Original mouse event object.
247
+ * @param {String} highlighterId Highlighter DIV element ID.
248
+ * @param {String} commandName Name of the command to execute.
249
+ * @return {Object} Passes out return value from command execution.
250
+ */
251
+ executeCommand : function(sender, event, highlighterId, commandName, args)
252
+ {
253
+ var highlighter = sh.vars.highlighters[highlighterId],
254
+ command
255
+ ;
256
+
257
+ if (highlighter == null || (command = highlighter.toolbarCommands[commandName]) == null)
258
+ return null;
259
+
260
+ return command.execute(sender, event, args);
261
+ },
262
+
263
+ /** Collection of toolbar items. */
264
+ items : {
265
+ expandSource : function(highlighter)
266
+ {
267
+ this.create = function()
268
+ {
269
+ if (highlighter.getParam('collapse') != true)
270
+ return;
271
+
272
+ return sh.config.strings.expandSource;
273
+ };
274
+
275
+ this.execute = function(sender, event, args)
276
+ {
277
+ var div = highlighter.div;
278
+
279
+ sender.parentNode.removeChild(sender);
280
+ div.className = div.className.replace('collapsed', '');
281
+ };
282
+ },
283
+
284
+ /**
285
+ * Command to open a new window and display the original unformatted source code inside.
286
+ */
287
+ viewSource : function(highlighter)
288
+ {
289
+ this.create = function()
290
+ {
291
+ return sh.config.strings.viewSource;
292
+ };
293
+
294
+ this.execute = function(sender, event, args)
295
+ {
296
+ var code = sh.utils.fixInputString(highlighter.originalCode).replace(/</g, '&lt;'),
297
+ wnd = sh.utils.popup('', '_blank', 750, 400, 'location=0, resizable=1, menubar=0, scrollbars=1')
298
+ ;
299
+
300
+ code = sh.utils.unindent(code);
301
+
302
+ wnd.document.write('<pre>' + code + '</pre>');
303
+ wnd.document.close();
304
+ };
305
+ },
306
+
307
+ /**
308
+ * Command to copy the original source code in to the clipboard.
309
+ * Uses Flash method if <code>clipboardSwf</code> is configured.
310
+ */
311
+ copyToClipboard : function(highlighter)
312
+ {
313
+ var flashDiv, flashSwf,
314
+ highlighterId = highlighter.id
315
+ ;
316
+
317
+ this.create = function()
318
+ {
319
+ var config = sh.config;
320
+
321
+ // disable functionality if running locally
322
+ if (config.clipboardSwf == null)
323
+ return null;
324
+
325
+ function params(list)
326
+ {
327
+ var result = '';
328
+
329
+ for (var name in list)
330
+ result += "<param name='" + name + "' value='" + list[name] + "'/>";
331
+
332
+ return result;
333
+ };
334
+
335
+ function attributes(list)
336
+ {
337
+ var result = '';
338
+
339
+ for (var name in list)
340
+ result += " " + name + "='" + list[name] + "'";
341
+
342
+ return result;
343
+ };
344
+
345
+ var args1 = {
346
+ width : config.toolbarItemWidth,
347
+ height : config.toolbarItemHeight,
348
+ id : highlighterId + '_clipboard',
349
+ type : 'application/x-shockwave-flash',
350
+ title : sh.config.strings.copyToClipboard
351
+ },
352
+
353
+ // these arguments are used in IE's <param /> collection
354
+ args2 = {
355
+ allowScriptAccess : 'always',
356
+ wmode : 'transparent',
357
+ flashVars : 'highlighterId=' + highlighterId,
358
+ menu : 'false'
359
+ },
360
+ swf = config.clipboardSwf,
361
+ html
362
+ ;
363
+
364
+ if (/msie/i.test(navigator.userAgent))
365
+ {
366
+ html = '<object'
367
+ + attributes({
368
+ classid : 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000',
369
+ codebase : 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0'
370
+ })
371
+ + attributes(args1)
372
+ + '>'
373
+ + params(args2)
374
+ + params({ movie : swf })
375
+ + '</object>'
376
+ ;
377
+ }
378
+ else
379
+ {
380
+ html = '<embed'
381
+ + attributes(args1)
382
+ + attributes(args2)
383
+ + attributes({ src : swf })
384
+ + '/>'
385
+ ;
386
+ }
387
+
388
+ flashDiv = document.createElement('div');
389
+ flashDiv.innerHTML = html;
390
+
391
+ return flashDiv;
392
+ };
393
+
394
+ this.execute = function(sender, event, args)
395
+ {
396
+ var command = args.command;
397
+
398
+ switch (command)
399
+ {
400
+ case 'get':
401
+ var code = sh.utils.unindent(
402
+ sh.utils.fixInputString(highlighter.originalCode)
403
+ .replace(/&lt;/g, '<')
404
+ .replace(/&gt;/g, '>')
405
+ .replace(/&amp;/g, '&')
406
+ );
407
+
408
+ if(window.clipboardData)
409
+ // will fall through to the confirmation because there isn't a break
410
+ window.clipboardData.setData('text', code);
411
+ else
412
+ return sh.utils.unindent(code);
413
+
414
+ case 'ok':
415
+ sh.utils.alert(sh.config.strings.copyToClipboardConfirmation);
416
+ break;
417
+
418
+ case 'error':
419
+ sh.utils.alert(args.message);
420
+ break;
421
+ }
422
+ };
423
+ },
424
+
425
+ /** Command to print the colored source code. */
426
+ printSource : function(highlighter)
427
+ {
428
+ this.create = function()
429
+ {
430
+ return sh.config.strings.print;
431
+ };
432
+
433
+ this.execute = function(sender, event, args)
434
+ {
435
+ var iframe = document.createElement('IFRAME'),
436
+ doc = null
437
+ ;
438
+
439
+ // make sure there is never more than one hidden iframe created by SH
440
+ if (sh.vars.printFrame != null)
441
+ document.body.removeChild(sh.vars.printFrame);
442
+
443
+ sh.vars.printFrame = iframe;
444
+
445
+ // this hides the iframe
446
+ iframe.style.cssText = 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;';
447
+
448
+ document.body.appendChild(iframe);
449
+ doc = iframe.contentWindow.document;
450
+
451
+ copyStyles(doc, window.document);
452
+ doc.write('<div class="' + highlighter.div.className.replace('collapsed', '') + ' printing">' + highlighter.div.innerHTML + '</div>');
453
+ doc.close();
454
+
455
+ iframe.contentWindow.focus();
456
+ iframe.contentWindow.print();
457
+
458
+ function copyStyles(destDoc, sourceDoc)
459
+ {
460
+ var links = sourceDoc.getElementsByTagName('link');
461
+
462
+ for(var i = 0; i < links.length; i++)
463
+ if(links[i].rel.toLowerCase() == 'stylesheet' && /shCore\.css$/.test(links[i].href))
464
+ destDoc.write('<link type="text/css" rel="stylesheet" href="' + links[i].href + '"></link>');
465
+ };
466
+ };
467
+ },
468
+
469
+ /** Command to display the about dialog window. */
470
+ about : function(highlighter)
471
+ {
472
+ this.create = function()
473
+ {
474
+ return sh.config.strings.help;
475
+ };
476
+
477
+ this.execute = function(sender, event)
478
+ {
479
+ var wnd = sh.utils.popup('', '_blank', 500, 250, 'scrollbars=0'),
480
+ doc = wnd.document
481
+ ;
482
+
483
+ doc.write(sh.config.strings.aboutDialog);
484
+ doc.close();
485
+ wnd.focus();
486
+ };
487
+ }
488
+ }
489
+ },
490
+
491
+ utils : {
492
+ /**
493
+ * Finds an index of element in the array.
494
+ * @ignore
495
+ * @param {Object} searchElement
496
+ * @param {Number} fromIndex
497
+ * @return {Number} Returns index of element if found; -1 otherwise.
498
+ */
499
+ indexOf : function(array, searchElement, fromIndex)
500
+ {
501
+ fromIndex = Math.max(fromIndex || 0, 0);
502
+
503
+ for (var i = fromIndex; i < array.length; i++)
504
+ if(array[i] == searchElement)
505
+ return i;
506
+
507
+ return -1;
508
+ },
509
+
510
+ /**
511
+ * Generates a unique element ID.
512
+ */
513
+ guid : function(prefix)
514
+ {
515
+ return prefix + Math.round(Math.random() * 1000000).toString();
516
+ },
517
+
518
+ /**
519
+ * Merges two objects. Values from obj2 override values in obj1.
520
+ * Function is NOT recursive and works only for one dimensional objects.
521
+ * @param {Object} obj1 First object.
522
+ * @param {Object} obj2 Second object.
523
+ * @return {Object} Returns combination of both objects.
524
+ */
525
+ merge: function(obj1, obj2)
526
+ {
527
+ var result = {}, name;
528
+
529
+ for (name in obj1)
530
+ result[name] = obj1[name];
531
+
532
+ for (name in obj2)
533
+ result[name] = obj2[name];
534
+
535
+ return result;
536
+ },
537
+
538
+ /**
539
+ * Attempts to convert string to boolean.
540
+ * @param {String} value Input string.
541
+ * @return {Boolean} Returns true if input was "true", false if input was "false" and value otherwise.
542
+ */
543
+ toBoolean: function(value)
544
+ {
545
+ switch (value)
546
+ {
547
+ case "true":
548
+ return true;
549
+
550
+ case "false":
551
+ return false;
552
+ }
553
+
554
+ return value;
555
+ },
556
+
557
+ /**
558
+ * Opens up a centered popup window.
559
+ * @param {String} url URL to open in the window.
560
+ * @param {String} name Popup name.
561
+ * @param {int} width Popup width.
562
+ * @param {int} height Popup height.
563
+ * @param {String} options window.open() options.
564
+ * @return {Window} Returns window instance.
565
+ */
566
+ popup: function(url, name, width, height, options)
567
+ {
568
+ var x = (screen.width - width) / 2,
569
+ y = (screen.height - height) / 2
570
+ ;
571
+
572
+ options += ', left=' + x +
573
+ ', top=' + y +
574
+ ', width=' + width +
575
+ ', height=' + height
576
+ ;
577
+ options = options.replace(/^,/, '');
578
+
579
+ var win = window.open(url, name, options);
580
+ win.focus();
581
+ return win;
582
+ },
583
+
584
+ /**
585
+ * Adds event handler to the target object.
586
+ * @param {Object} obj Target object.
587
+ * @param {String} type Name of the event.
588
+ * @param {Function} func Handling function.
589
+ */
590
+ addEvent: function(obj, type, func)
591
+ {
592
+ if (obj.attachEvent)
593
+ {
594
+ obj['e' + type + func] = func;
595
+ obj[type + func] = function()
596
+ {
597
+ obj['e' + type + func](window.event);
598
+ }
599
+ obj.attachEvent('on' + type, obj[type + func]);
600
+ }
601
+ else
602
+ {
603
+ obj.addEventListener(type, func, false);
604
+ }
605
+ },
606
+
607
+ /**
608
+ * Displays an alert.
609
+ * @param {String} str String to display.
610
+ */
611
+ alert: function(str)
612
+ {
613
+ alert(sh.config.strings.alert + str)
614
+ },
615
+
616
+ /**
617
+ * Finds a brush by its alias.
618
+ *
619
+ * @param {String} alias Brush alias.
620
+ * @param {Boolean} alert Suppresses the alert if false.
621
+ * @return {Brush} Returns bursh constructor if found, null otherwise.
622
+ */
623
+ findBrush: function(alias, alert)
624
+ {
625
+ var brushes = sh.vars.discoveredBrushes,
626
+ result = null
627
+ ;
628
+
629
+ if (brushes == null)
630
+ {
631
+ brushes = {};
632
+
633
+ // Find all brushes
634
+ for (var brush in sh.brushes)
635
+ {
636
+ var aliases = sh.brushes[brush].aliases;
637
+
638
+ if (aliases == null)
639
+ continue;
640
+
641
+ // keep the brush name
642
+ sh.brushes[brush].name = brush.toLowerCase();
643
+
644
+ for (var i = 0; i < aliases.length; i++)
645
+ brushes[aliases[i]] = brush;
646
+ }
647
+
648
+ sh.vars.discoveredBrushes = brushes;
649
+ }
650
+
651
+ result = sh.brushes[brushes[alias]];
652
+
653
+ if (result == null && alert != false)
654
+ sh.utils.alert(sh.config.strings.noBrush + alias);
655
+
656
+ return result;
657
+ },
658
+
659
+ /**
660
+ * Executes a callback on each line and replaces each line with result from the callback.
661
+ * @param {Object} str Input string.
662
+ * @param {Object} callback Callback function taking one string argument and returning a string.
663
+ */
664
+ eachLine: function(str, callback)
665
+ {
666
+ var lines = str.split('\n');
667
+
668
+ for (var i = 0; i < lines.length; i++)
669
+ lines[i] = callback(lines[i]);
670
+
671
+ return lines.join('\n');
672
+ },
673
+
674
+ /**
675
+ * This is a special trim which only removes first and last empty lines
676
+ * and doesn't affect valid leading space on the first line.
677
+ *
678
+ * @param {String} str Input string
679
+ * @return {String} Returns string without empty first and last lines.
680
+ */
681
+ trimFirstAndLastLines: function(str)
682
+ {
683
+ return str.replace(/^[ ]*[\n]+|[\n]*[ ]*$/g, '');
684
+ },
685
+
686
+ /**
687
+ * Parses key/value pairs into hash object.
688
+ *
689
+ * Understands the following formats:
690
+ * - name: word;
691
+ * - name: [word, word];
692
+ * - name: "string";
693
+ * - name: 'string';
694
+ *
695
+ * For example:
696
+ * name1: value; name2: [value, value]; name3: 'value'
697
+ *
698
+ * @param {String} str Input string.
699
+ * @return {Object} Returns deserialized object.
700
+ */
701
+ parseParams: function(str)
702
+ {
703
+ var match,
704
+ result = {},
705
+ arrayRegex = new XRegExp("^\\[(?<values>(.*?))\\]$"),
706
+ regex = new XRegExp(
707
+ "(?<name>[\\w-]+)" +
708
+ "\\s*:\\s*" +
709
+ "(?<value>" +
710
+ "[\\w-%#]+|" + // word
711
+ "\\[.*?\\]|" + // [] array
712
+ '".*?"|' + // "" string
713
+ "'.*?'" + // '' string
714
+ ")\\s*;?",
715
+ "g"
716
+ )
717
+ ;
718
+
719
+ while ((match = regex.exec(str)) != null)
720
+ {
721
+ var value = match.value
722
+ .replace(/^['"]|['"]$/g, '') // strip quotes from end of strings
723
+ ;
724
+
725
+ // try to parse array value
726
+ if (value != null && arrayRegex.test(value))
727
+ {
728
+ var m = arrayRegex.exec(value);
729
+ value = m.values.length > 0 ? m.values.split(/\s*,\s*/) : [];
730
+ }
731
+
732
+ result[match.name] = value;
733
+ }
734
+
735
+ return result;
736
+ },
737
+
738
+ /**
739
+ * Wraps each line of the string into <code/> tag with given style applied to it.
740
+ *
741
+ * @param {String} str Input string.
742
+ * @param {String} css Style name to apply to the string.
743
+ * @return {String} Returns input string with each line surrounded by <span/> tag.
744
+ */
745
+ decorate: function(str, css)
746
+ {
747
+ if (str == null || str.length == 0 || str == '\n')
748
+ return str;
749
+
750
+ str = str.replace(/</g, '&lt;');
751
+
752
+ // Replace two or more sequential spaces with &nbsp; leaving last space untouched.
753
+ str = str.replace(/ {2,}/g, function(m)
754
+ {
755
+ var spaces = '';
756
+
757
+ for (var i = 0; i < m.length - 1; i++)
758
+ spaces += '&nbsp;';
759
+
760
+ return spaces + ' ';
761
+ });
762
+
763
+ // Split each line and apply <span class="...">...</span> to them so that
764
+ // leading spaces aren't included.
765
+ if (css != null)
766
+ str = sh.utils.eachLine(str, function(line)
767
+ {
768
+ if (line.length == 0)
769
+ return '';
770
+
771
+ var spaces = '';
772
+
773
+ line = line.replace(/^(&nbsp;| )+/, function(s)
774
+ {
775
+ spaces = s;
776
+ return '';
777
+ });
778
+
779
+ if (line.length == 0)
780
+ return spaces;
781
+
782
+ return spaces + '<code class="' + css + '">' + line + '</code>';
783
+ });
784
+
785
+ return str;
786
+ },
787
+
788
+ /**
789
+ * Pads number with zeros until it's length is the same as given length.
790
+ *
791
+ * @param {Number} number Number to pad.
792
+ * @param {Number} length Max string length with.
793
+ * @return {String} Returns a string padded with proper amount of '0'.
794
+ */
795
+ padNumber : function(number, length)
796
+ {
797
+ var result = number.toString();
798
+
799
+ while (result.length < length)
800
+ result = '0' + result;
801
+
802
+ return result;
803
+ },
804
+
805
+ /**
806
+ * Measures width of a single space character.
807
+ * @return {Number} Returns width of a single space character.
808
+ */
809
+ measureSpace : function()
810
+ {
811
+ var container = document.createElement('div'),
812
+ span,
813
+ result = 0,
814
+ body = document.body,
815
+ id = sh.utils.guid('measureSpace'),
816
+
817
+ // variable names will be compressed, so it's better than a plain string
818
+ divOpen = '<div class="',
819
+ closeDiv = '</div>',
820
+ closeSpan = '</span>'
821
+ ;
822
+
823
+ // we have to duplicate highlighter nested structure in order to get an acurate space measurment
824
+ container.innerHTML =
825
+ divOpen + 'syntaxhighlighter">'
826
+ + divOpen + 'lines">'
827
+ + divOpen + 'line">'
828
+ + divOpen + 'content'
829
+ + '"><span class="block"><span id="' + id + '">&nbsp;' + closeSpan + closeSpan
830
+ + closeDiv
831
+ + closeDiv
832
+ + closeDiv
833
+ + closeDiv
834
+ ;
835
+
836
+ body.appendChild(container);
837
+ span = document.getElementById(id);
838
+
839
+ if (/opera/i.test(navigator.userAgent))
840
+ {
841
+ var style = window.getComputedStyle(span, null);
842
+ result = parseInt(style.getPropertyValue("width"));
843
+ }
844
+ else
845
+ {
846
+ result = span.offsetWidth;
847
+ }
848
+
849
+ body.removeChild(container);
850
+
851
+ return result;
852
+ },
853
+
854
+ /**
855
+ * Replaces tabs with spaces.
856
+ *
857
+ * @param {String} code Source code.
858
+ * @param {Number} tabSize Size of the tab.
859
+ * @return {String} Returns code with all tabs replaces by spaces.
860
+ */
861
+ processTabs : function(code, tabSize)
862
+ {
863
+ var tab = '';
864
+
865
+ for (var i = 0; i < tabSize; i++)
866
+ tab += ' ';
867
+
868
+ return code.replace(/\t/g, tab);
869
+ },
870
+
871
+ /**
872
+ * Replaces tabs with smart spaces.
873
+ *
874
+ * @param {String} code Code to fix the tabs in.
875
+ * @param {Number} tabSize Number of spaces in a column.
876
+ * @return {String} Returns code with all tabs replaces with roper amount of spaces.
877
+ */
878
+ processSmartTabs : function(code, tabSize)
879
+ {
880
+ var lines = code.split('\n'),
881
+ tab = '\t',
882
+ spaces = ''
883
+ ;
884
+
885
+ // Create a string with 1000 spaces to copy spaces from...
886
+ // It's assumed that there would be no indentation longer than that.
887
+ for (var i = 0; i < 50; i++)
888
+ spaces += ' '; // 20 spaces * 50
889
+
890
+ // This function inserts specified amount of spaces in the string
891
+ // where a tab is while removing that given tab.
892
+ function insertSpaces(line, pos, count)
893
+ {
894
+ return line.substr(0, pos)
895
+ + spaces.substr(0, count)
896
+ + line.substr(pos + 1, line.length) // pos + 1 will get rid of the tab
897
+ ;
898
+ };
899
+
900
+ // Go through all the lines and do the 'smart tabs' magic.
901
+ code = sh.utils.eachLine(code, function(line)
902
+ {
903
+ if (line.indexOf(tab) == -1)
904
+ return line;
905
+
906
+ var pos = 0;
907
+
908
+ while ((pos = line.indexOf(tab)) != -1)
909
+ {
910
+ // This is pretty much all there is to the 'smart tabs' logic.
911
+ // Based on the position within the line and size of a tab,
912
+ // calculate the amount of spaces we need to insert.
913
+ var spaces = tabSize - pos % tabSize;
914
+ line = insertSpaces(line, pos, spaces);
915
+ }
916
+
917
+ return line;
918
+ });
919
+
920
+ return code;
921
+ },
922
+
923
+ /**
924
+ * Performs various string fixes based on configuration.
925
+ */
926
+ fixInputString : function(str)
927
+ {
928
+ var br = /<br\s*\/?>|&lt;br\s*\/?&gt;/gi;
929
+
930
+ if (sh.config.bloggerMode == true)
931
+ str = str.replace(br, '\n');
932
+
933
+ if (sh.config.stripBrs == true)
934
+ str = str.replace(br, '');
935
+
936
+ return str;
937
+ },
938
+
939
+ /**
940
+ * Removes all white space at the begining and end of a string.
941
+ *
942
+ * @param {String} str String to trim.
943
+ * @return {String} Returns string without leading and following white space characters.
944
+ */
945
+ trim: function(str)
946
+ {
947
+ return str.replace(/^\s+|\s+$/g, '');
948
+ },
949
+
950
+ /**
951
+ * Unindents a block of text by the lowest common indent amount.
952
+ * @param {String} str Text to unindent.
953
+ * @return {String} Returns unindented text block.
954
+ */
955
+ unindent: function(str)
956
+ {
957
+ var lines = sh.utils.fixInputString(str).split('\n'),
958
+ indents = new Array(),
959
+ regex = /^\s*/,
960
+ min = 1000
961
+ ;
962
+
963
+ // go through every line and check for common number of indents
964
+ for (var i = 0; i < lines.length && min > 0; i++)
965
+ {
966
+ var line = lines[i];
967
+
968
+ if (sh.utils.trim(line).length == 0)
969
+ continue;
970
+
971
+ var matches = regex.exec(line);
972
+
973
+ // In the event that just one line doesn't have leading white space
974
+ // we can't unindent anything, so bail completely.
975
+ if (matches == null)
976
+ return str;
977
+
978
+ min = Math.min(matches[0].length, min);
979
+ }
980
+
981
+ // trim minimum common number of white space from the begining of every line
982
+ if (min > 0)
983
+ for (var i = 0; i < lines.length; i++)
984
+ lines[i] = lines[i].substr(min);
985
+
986
+ return lines.join('\n');
987
+ },
988
+
989
+ /**
990
+ * Callback method for Array.sort() which sorts matches by
991
+ * index position and then by length.
992
+ *
993
+ * @param {Match} m1 Left object.
994
+ * @param {Match} m2 Right object.
995
+ * @return {Number} Returns -1, 0 or -1 as a comparison result.
996
+ */
997
+ matchesSortCallback: function(m1, m2)
998
+ {
999
+ // sort matches by index first
1000
+ if(m1.index < m2.index)
1001
+ return -1;
1002
+ else if(m1.index > m2.index)
1003
+ return 1;
1004
+ else
1005
+ {
1006
+ // if index is the same, sort by length
1007
+ if(m1.length < m2.length)
1008
+ return -1;
1009
+ else if(m1.length > m2.length)
1010
+ return 1;
1011
+ }
1012
+
1013
+ return 0;
1014
+ },
1015
+
1016
+ /**
1017
+ * Executes given regular expression on provided code and returns all
1018
+ * matches that are found.
1019
+ *
1020
+ * @param {String} code Code to execute regular expression on.
1021
+ * @param {Object} regex Regular expression item info from <code>regexList</code> collection.
1022
+ * @return {Array} Returns a list of Match objects.
1023
+ */
1024
+ getMatches: function(code, regexInfo)
1025
+ {
1026
+ function defaultAdd(match, regexInfo)
1027
+ {
1028
+ return [new sh.Match(match[0], match.index, regexInfo.css)];
1029
+ };
1030
+
1031
+ var index = 0,
1032
+ match = null,
1033
+ result = [],
1034
+ func = regexInfo.func ? regexInfo.func : defaultAdd
1035
+ ;
1036
+
1037
+ while((match = regexInfo.regex.exec(code)) != null)
1038
+ result = result.concat(func(match, regexInfo));
1039
+
1040
+ return result;
1041
+ },
1042
+
1043
+ processUrls: function(code)
1044
+ {
1045
+ var lt = '&lt;',
1046
+ gt = '&gt;'
1047
+ ;
1048
+
1049
+ return code.replace(sh.regexLib.url, function(m)
1050
+ {
1051
+ var suffix = '', prefix = '';
1052
+
1053
+ // We include &lt; and &gt; in the URL for the common cases like <http://google.com>
1054
+ // The problem is that they get transformed into &lt;http://google.com&gt;
1055
+ // Where as &gt; easily looks like part of the URL string.
1056
+
1057
+ if (m.indexOf(lt) == 0)
1058
+ {
1059
+ prefix = lt;
1060
+ m = m.substring(lt.length);
1061
+ }
1062
+
1063
+ if (m.indexOf(gt) == m.length - gt.length)
1064
+ {
1065
+ m = m.substring(0, m.length - gt.length);
1066
+ suffix = gt;
1067
+ }
1068
+
1069
+ return prefix + '<a href="' + m + '">' + m + '</a>' + suffix;
1070
+ });
1071
+ },
1072
+
1073
+ /**
1074
+ * Finds all <SCRIPT TYPE="syntaxhighlighter" /> elements.
1075
+ * @return {Array} Returns array of all found SyntaxHighlighter tags.
1076
+ */
1077
+ getSyntaxHighlighterScriptTags: function()
1078
+ {
1079
+ var tags = document.getElementsByTagName('script'),
1080
+ result = []
1081
+ ;
1082
+
1083
+ for (var i = 0; i < tags.length; i++)
1084
+ if (tags[i].type == 'syntaxhighlighter')
1085
+ result.push(tags[i]);
1086
+
1087
+ return result;
1088
+ },
1089
+
1090
+ /**
1091
+ * Strips <![CDATA[]]> from <SCRIPT /> content because it should be used
1092
+ * there in most cases for XHTML compliance.
1093
+ * @param {String} original Input code.
1094
+ * @return {String} Returns code without leading <![CDATA[]]> tags.
1095
+ */
1096
+ stripCData: function(original)
1097
+ {
1098
+ var left = '<![CDATA[',
1099
+ right = ']]>',
1100
+ // for some reason IE inserts some leading blanks here
1101
+ copy = sh.utils.trim(original),
1102
+ changed = false
1103
+ ;
1104
+
1105
+ if (copy.indexOf(left) == 0)
1106
+ {
1107
+ copy = copy.substring(left.length);
1108
+ changed = true;
1109
+ }
1110
+
1111
+ if (copy.indexOf(right) == copy.length - right.length)
1112
+ {
1113
+ copy = copy.substring(0, copy.length - right.length);
1114
+ changed = true;
1115
+ }
1116
+
1117
+ return changed ? copy : original;
1118
+ }
1119
+ }, // end of utils
1120
+
1121
+ /**
1122
+ * Shorthand to highlight all elements on the page that are marked as
1123
+ * SyntaxHighlighter source code.
1124
+ *
1125
+ * @param {Object} globalParams Optional parameters which override element's
1126
+ * parameters. Only used if element is specified.
1127
+ *
1128
+ * @param {Object} element Optional element to highlight. If none is
1129
+ * provided, all elements in the current document
1130
+ * are highlighted.
1131
+ */
1132
+ highlight : function(globalParams, element)
1133
+ {
1134
+ function toArray(source)
1135
+ {
1136
+ var result = [];
1137
+
1138
+ for (var i = 0; i < source.length; i++)
1139
+ result.push(source[i]);
1140
+
1141
+ return result;
1142
+ };
1143
+
1144
+ var elements = element ? [element] : toArray(document.getElementsByTagName(sh.config.tagName)),
1145
+ propertyName = 'innerHTML',
1146
+ highlighter = null,
1147
+ conf = sh.config
1148
+ ;
1149
+
1150
+ // support for <SCRIPT TYPE="syntaxhighlighter" /> feature
1151
+ if (conf.useScriptTags)
1152
+ elements = elements.concat(sh.utils.getSyntaxHighlighterScriptTags());
1153
+
1154
+ if (elements.length === 0)
1155
+ return;
1156
+
1157
+ for (var i = 0; i < elements.length; i++)
1158
+ {
1159
+ var target = elements[i],
1160
+ params = sh.utils.parseParams(target.className),
1161
+ brushName,
1162
+ code,
1163
+ result
1164
+ ;
1165
+
1166
+ // local params take precedence over globals
1167
+ params = sh.utils.merge(globalParams, params);
1168
+ brushName = params['brush'];
1169
+
1170
+ if (brushName == null)
1171
+ continue;
1172
+
1173
+ // Instantiate a brush
1174
+ if (params['html-script'] == 'true' || sh.defaults['html-script'] == true)
1175
+ {
1176
+ highlighter = new sh.HtmlScript(brushName);
1177
+ brushName = 'htmlscript';
1178
+ }
1179
+ else
1180
+ {
1181
+ var brush = sh.utils.findBrush(brushName);
1182
+
1183
+ if (brush)
1184
+ {
1185
+ brushName = brush.name;
1186
+ highlighter = new brush();
1187
+ }
1188
+ else
1189
+ {
1190
+ continue;
1191
+ }
1192
+ }
1193
+
1194
+ code = target[propertyName];
1195
+
1196
+ // remove CDATA from <SCRIPT/> tags if it's present
1197
+ if (conf.useScriptTags)
1198
+ code = sh.utils.stripCData(code);
1199
+
1200
+ params['brush-name'] = brushName;
1201
+ highlighter.highlight(code, params);
1202
+
1203
+ result = highlighter.div;
1204
+
1205
+ if (sh.config.debug)
1206
+ {
1207
+ result = document.createElement('textarea');
1208
+ result.value = highlighter.div.innerHTML;
1209
+ result.style.width = '70em';
1210
+ result.style.height = '30em';
1211
+ }
1212
+
1213
+ target.parentNode.replaceChild(result, target);
1214
+ }
1215
+ },
1216
+
1217
+ /**
1218
+ * Main entry point for the SyntaxHighlighter.
1219
+ * @param {Object} params Optional params to apply to all highlighted elements.
1220
+ */
1221
+ all : function(params)
1222
+ {
1223
+ sh.utils.addEvent(
1224
+ window,
1225
+ 'load',
1226
+ function() { sh.highlight(params); }
1227
+ );
1228
+ }
1229
+ }; // end of sh
1230
+
1231
+ /**
1232
+ * Match object.
1233
+ */
1234
+ sh.Match = function(value, index, css)
1235
+ {
1236
+ this.value = value;
1237
+ this.index = index;
1238
+ this.length = value.length;
1239
+ this.css = css;
1240
+ this.brushName = null;
1241
+ };
1242
+
1243
+ sh.Match.prototype.toString = function()
1244
+ {
1245
+ return this.value;
1246
+ };
1247
+
1248
+ /**
1249
+ * Simulates HTML code with a scripting language embedded.
1250
+ *
1251
+ * @param {String} scriptBrushName Brush name of the scripting language.
1252
+ */
1253
+ sh.HtmlScript = function(scriptBrushName)
1254
+ {
1255
+ var brushClass = sh.utils.findBrush(scriptBrushName),
1256
+ scriptBrush,
1257
+ xmlBrush = new sh.brushes.Xml(),
1258
+ bracketsRegex = null
1259
+ ;
1260
+
1261
+ if (brushClass == null)
1262
+ return;
1263
+
1264
+ scriptBrush = new brushClass();
1265
+ this.xmlBrush = xmlBrush;
1266
+
1267
+ if (scriptBrush.htmlScript == null)
1268
+ {
1269
+ sh.utils.alert(sh.config.strings.brushNotHtmlScript + scriptBrushName);
1270
+ return;
1271
+ }
1272
+
1273
+ xmlBrush.regexList.push(
1274
+ { regex: scriptBrush.htmlScript.code, func: process }
1275
+ );
1276
+
1277
+ function offsetMatches(matches, offset)
1278
+ {
1279
+ for (var j = 0; j < matches.length; j++)
1280
+ matches[j].index += offset;
1281
+ }
1282
+
1283
+ function process(match, info)
1284
+ {
1285
+ var code = match.code,
1286
+ matches = [],
1287
+ regexList = scriptBrush.regexList,
1288
+ offset = match.index + match.left.length,
1289
+ htmlScript = scriptBrush.htmlScript,
1290
+ result
1291
+ ;
1292
+
1293
+ // add all matches from the code
1294
+ for (var i = 0; i < regexList.length; i++)
1295
+ {
1296
+ result = sh.utils.getMatches(code, regexList[i]);
1297
+ offsetMatches(result, offset);
1298
+ matches = matches.concat(result);
1299
+ }
1300
+
1301
+ // add left script bracket
1302
+ if (htmlScript.left != null && match.left != null)
1303
+ {
1304
+ result = sh.utils.getMatches(match.left, htmlScript.left);
1305
+ offsetMatches(result, match.index);
1306
+ matches = matches.concat(result);
1307
+ }
1308
+
1309
+ // add right script bracket
1310
+ if (htmlScript.right != null && match.right != null)
1311
+ {
1312
+ result = sh.utils.getMatches(match.right, htmlScript.right);
1313
+ offsetMatches(result, match.index + match[0].lastIndexOf(match.right));
1314
+ matches = matches.concat(result);
1315
+ }
1316
+
1317
+ for (var j = 0; j < matches.length; j++)
1318
+ matches[j].brushName = brushClass.name;
1319
+
1320
+ return matches;
1321
+ }
1322
+ };
1323
+
1324
+ sh.HtmlScript.prototype.highlight = function(code, params)
1325
+ {
1326
+ this.xmlBrush.highlight(code, params);
1327
+ this.div = this.xmlBrush.div;
1328
+ }
1329
+
1330
+ /**
1331
+ * Main Highlither class.
1332
+ * @constructor
1333
+ */
1334
+ sh.Highlighter = function()
1335
+ {
1336
+ };
1337
+
1338
+ sh.Highlighter.prototype = {
1339
+ /**
1340
+ * Returns value of the parameter passed to the highlighter.
1341
+ * @param {String} name Name of the parameter.
1342
+ * @param {Object} defaultValue Default value.
1343
+ * @return {Object} Returns found value or default value otherwise.
1344
+ */
1345
+ getParam : function(name, defaultValue)
1346
+ {
1347
+ var result = this.params[name];
1348
+ return sh.utils.toBoolean(result == null ? defaultValue : result);
1349
+ },
1350
+
1351
+ /**
1352
+ * Shortcut to document.createElement().
1353
+ * @param {String} name Name of the element to create (DIV, A, etc).
1354
+ * @return {HTMLElement} Returns new HTML element.
1355
+ */
1356
+ create: function(name)
1357
+ {
1358
+ return document.createElement(name);
1359
+ },
1360
+
1361
+ /**
1362
+ * Applies all regular expression to the code and stores all found
1363
+ * matches in the `this.matches` array.
1364
+ * @param {Array} regexList List of regular expressions.
1365
+ * @param {String} code Source code.
1366
+ * @return {Array} Returns list of matches.
1367
+ */
1368
+ findMatches: function(regexList, code)
1369
+ {
1370
+ var result = [];
1371
+
1372
+ if (regexList != null)
1373
+ for (var i = 0; i < regexList.length; i++)
1374
+ // BUG: length returns len+1 for array if methods added to prototype chain (oising@gmail.com)
1375
+ if (typeof (regexList[i]) == "object")
1376
+ result = result.concat(sh.utils.getMatches(code, regexList[i]));
1377
+
1378
+ // sort the matches
1379
+ return result.sort(sh.utils.matchesSortCallback);
1380
+ },
1381
+
1382
+ /**
1383
+ * Checks to see if any of the matches are inside of other matches.
1384
+ * This process would get rid of highligted strings inside comments,
1385
+ * keywords inside strings and so on.
1386
+ */
1387
+ removeNestedMatches: function()
1388
+ {
1389
+ var matches = this.matches;
1390
+
1391
+ // Optimized by Jose Prado (http://joseprado.com)
1392
+ for (var i = 0; i < matches.length; i++)
1393
+ {
1394
+ if (matches[i] === null)
1395
+ continue;
1396
+
1397
+ var itemI = matches[i],
1398
+ itemIEndPos = itemI.index + itemI.length
1399
+ ;
1400
+
1401
+ for (var j = i + 1; j < matches.length && matches[i] !== null; j++)
1402
+ {
1403
+ var itemJ = matches[j];
1404
+
1405
+ if (itemJ === null)
1406
+ continue;
1407
+ else if (itemJ.index > itemIEndPos)
1408
+ break;
1409
+ else if (itemJ.index == itemI.index && itemJ.length > itemI.length)
1410
+ this.matches[i] = null;
1411
+ else if (itemJ.index >= itemI.index && itemJ.index < itemIEndPos)
1412
+ this.matches[j] = null;
1413
+ }
1414
+ }
1415
+ },
1416
+
1417
+ /**
1418
+ * Splits block of text into individual DIV lines.
1419
+ * @param {String} code Code to highlight.
1420
+ * @return {String} Returns highlighted code in HTML form.
1421
+ */
1422
+ createDisplayLines : function(code)
1423
+ {
1424
+ var lines = code.split(/\n/g),
1425
+ firstLine = parseInt(this.getParam('first-line')),
1426
+ padLength = this.getParam('pad-line-numbers'),
1427
+ highlightedLines = this.getParam('highlight', []),
1428
+ hasGutter = this.getParam('gutter')
1429
+ ;
1430
+
1431
+ code = '';
1432
+
1433
+ if (padLength == true)
1434
+ padLength = (firstLine + lines.length - 1).toString().length;
1435
+ else if (isNaN(padLength) == true)
1436
+ padLength = 0;
1437
+
1438
+ for (var i = 0; i < lines.length; i++)
1439
+ {
1440
+ var line = lines[i],
1441
+ indent = /^(&nbsp;|\s)+/.exec(line),
1442
+ lineClass = 'alt' + (i % 2 == 0 ? 1 : 2),
1443
+ lineNumber = sh.utils.padNumber(firstLine + i, padLength),
1444
+ highlighted = sh.utils.indexOf(highlightedLines, (firstLine + i).toString()) != -1,
1445
+ spaces = null
1446
+ ;
1447
+
1448
+ if (indent != null)
1449
+ {
1450
+ spaces = indent[0].toString();
1451
+ line = line.substr(spaces.length);
1452
+ }
1453
+
1454
+ line = sh.utils.trim(line);
1455
+
1456
+ if (line.length == 0)
1457
+ line = '&nbsp;';
1458
+
1459
+ if (highlighted)
1460
+ lineClass += ' highlighted';
1461
+
1462
+ code +=
1463
+ '<div class="line ' + lineClass + '">'
1464
+ + '<table>'
1465
+ + '<tr>'
1466
+ + (hasGutter ? '<td class="number"><code>' + lineNumber + '</code></td>' : '')
1467
+ + '<td class="content">'
1468
+ + (spaces != null ? '<code class="spaces">' + spaces.replace(' ', '&nbsp;') + '</code>' : '')
1469
+ + line
1470
+ + '</td>'
1471
+ + '</tr>'
1472
+ + '</table>'
1473
+ + '</div>'
1474
+ ;
1475
+ }
1476
+
1477
+ return code;
1478
+ },
1479
+
1480
+ /**
1481
+ * Finds all matches in the source code.
1482
+ * @param {String} code Source code to process matches in.
1483
+ * @param {Array} matches Discovered regex matches.
1484
+ * @return {String} Returns formatted HTML with processed mathes.
1485
+ */
1486
+ processMatches: function(code, matches)
1487
+ {
1488
+ var pos = 0,
1489
+ result = '',
1490
+ decorate = sh.utils.decorate, // make an alias to save some bytes
1491
+ brushName = this.getParam('brush-name', '')
1492
+ ;
1493
+
1494
+ function getBrushNameCss(match)
1495
+ {
1496
+ var result = match ? (match.brushName || brushName) : brushName;
1497
+ return result ? result + ' ' : '';
1498
+ };
1499
+
1500
+ // Finally, go through the final list of matches and pull the all
1501
+ // together adding everything in between that isn't a match.
1502
+ for (var i = 0; i < matches.length; i++)
1503
+ {
1504
+ var match = matches[i],
1505
+ matchBrushName
1506
+ ;
1507
+
1508
+ if (match === null || match.length === 0)
1509
+ continue;
1510
+
1511
+ matchBrushName = getBrushNameCss(match);
1512
+
1513
+ result += decorate(code.substr(pos, match.index - pos), matchBrushName + 'plain')
1514
+ + decorate(match.value, matchBrushName + match.css)
1515
+ ;
1516
+
1517
+ pos = match.index + match.length;
1518
+ }
1519
+
1520
+ // don't forget to add whatever's remaining in the string
1521
+ result += decorate(code.substr(pos), getBrushNameCss() + 'plain');
1522
+
1523
+ return result;
1524
+ },
1525
+
1526
+ /**
1527
+ * Highlights the code and returns complete HTML.
1528
+ * @param {String} code Code to highlight.
1529
+ * @param {Object} params Parameters object.
1530
+ */
1531
+ highlight: function(code, params)
1532
+ {
1533
+ // using variables for shortcuts because JS compressor will shorten local variable names
1534
+ var conf = sh.config,
1535
+ vars = sh.vars,
1536
+ div,
1537
+ divClassName,
1538
+ tabSize,
1539
+ important = 'important'
1540
+ ;
1541
+
1542
+ this.params = {};
1543
+ this.div = null;
1544
+ this.lines = null;
1545
+ this.code = null;
1546
+ this.bar = null;
1547
+ this.toolbarCommands = {};
1548
+ this.id = sh.utils.guid('highlighter_');
1549
+
1550
+ // register this instance in the highlighters list
1551
+ vars.highlighters[this.id] = this;
1552
+
1553
+ if (code === null)
1554
+ code = '';
1555
+
1556
+ // local params take precedence over defaults
1557
+ this.params = sh.utils.merge(sh.defaults, params || {});
1558
+
1559
+ // process light mode
1560
+ if (this.getParam('light') == true)
1561
+ this.params.toolbar = this.params.gutter = false;
1562
+
1563
+ this.div = div = this.create('DIV');
1564
+ this.lines = this.create('DIV');
1565
+ this.lines.className = 'lines';
1566
+
1567
+ className = 'syntaxhighlighter';
1568
+ div.id = this.id;
1569
+
1570
+ // make collapsed
1571
+ if (this.getParam('collapse'))
1572
+ className += ' collapsed';
1573
+
1574
+ // disable gutter
1575
+ if (this.getParam('gutter') == false)
1576
+ className += ' nogutter';
1577
+
1578
+ // disable line wrapping
1579
+ if (this.getParam('wrap-lines') == false)
1580
+ this.lines.className += ' no-wrap';
1581
+
1582
+ // add custom user style name
1583
+ className += ' ' + this.getParam('class-name');
1584
+
1585
+ // add brush alias to the class name for custom CSS
1586
+ className += ' ' + this.getParam('brush-name');
1587
+
1588
+ div.className = className;
1589
+
1590
+ this.originalCode = code;
1591
+ this.code = sh.utils.trimFirstAndLastLines(code)
1592
+ .replace(/\r/g, ' ') // IE lets these buggers through
1593
+ ;
1594
+
1595
+ tabSize = this.getParam('tab-size');
1596
+
1597
+ // replace tabs with spaces
1598
+ this.code = this.getParam('smart-tabs') == true
1599
+ ? sh.utils.processSmartTabs(this.code, tabSize)
1600
+ : sh.utils.processTabs(this.code, tabSize)
1601
+ ;
1602
+
1603
+ this.code = sh.utils.unindent(this.code);
1604
+
1605
+ // add controls toolbar
1606
+ if (this.getParam('toolbar'))
1607
+ {
1608
+ this.bar = this.create('DIV');
1609
+ this.bar.className = 'bar';
1610
+ this.bar.appendChild(sh.toolbar.create(this));
1611
+ div.appendChild(this.bar);
1612
+
1613
+ // set up toolbar rollover
1614
+ var bar = this.bar;
1615
+ function hide() { bar.className = bar.className.replace('show', ''); }
1616
+ div.onmouseover = function() { hide(); bar.className += ' show'; };
1617
+ div.onmouseout = function() { hide(); }
1618
+ }
1619
+
1620
+ div.appendChild(this.lines);
1621
+
1622
+ this.matches = this.findMatches(this.regexList, this.code);
1623
+ this.removeNestedMatches();
1624
+
1625
+ code = this.processMatches(this.code, this.matches);
1626
+
1627
+ // finally, split all lines so that they wrap well
1628
+ code = this.createDisplayLines(sh.utils.trim(code));
1629
+
1630
+ // finally, process the links
1631
+ if (this.getParam('auto-links'))
1632
+ code = sh.utils.processUrls(code);
1633
+
1634
+ this.lines.innerHTML = code;
1635
+ },
1636
+
1637
+ /**
1638
+ * Converts space separated list of keywords into a regular expression string.
1639
+ * @param {String} str Space separated keywords.
1640
+ * @return {String} Returns regular expression string.
1641
+ */
1642
+ getKeywords: function(str)
1643
+ {
1644
+ str = str
1645
+ .replace(/^\s+|\s+$/g, '')
1646
+ .replace(/\s+/g, '|')
1647
+ ;
1648
+
1649
+ return '\\b(?:' + str + ')\\b';
1650
+ },
1651
+
1652
+ /**
1653
+ * Makes a brush compatible with the `html-script` functionality.
1654
+ * @param {Object} regexGroup Object containing `left` and `right` regular expressions.
1655
+ */
1656
+ forHtmlScript: function(regexGroup)
1657
+ {
1658
+ this.htmlScript = {
1659
+ left : { regex: regexGroup.left, css: 'script' },
1660
+ right : { regex: regexGroup.right, css: 'script' },
1661
+ code : new XRegExp(
1662
+ "(?<left>" + regexGroup.left.source + ")" +
1663
+ "(?<code>.*?)" +
1664
+ "(?<right>" + regexGroup.right.source + ")",
1665
+ "sgi"
1666
+ )
1667
+ };
1668
+ }
1669
+ }; // end of Highlighter
1670
+
1671
+ return sh;
1672
+ }(); // end of anonymous function
1673
+
1674
+
1675
+ /**
1676
+ * XRegExp 0.6.1
1677
+ * (c) 2007-2008 Steven Levithan
1678
+ * <http://stevenlevithan.com/regex/xregexp/>
1679
+ * MIT License
1680
+ *
1681
+ * provides an augmented, cross-browser implementation of regular expressions
1682
+ * including support for additional modifiers and syntax. several convenience
1683
+ * methods and a recursive-construct parser are also included.
1684
+ */
1685
+
1686
+ // prevent running twice, which would break references to native globals
1687
+ if (!window.XRegExp) {
1688
+ // anonymous function to avoid global variables
1689
+ (function () {
1690
+ // copy various native globals for reference. can't use the name ``native``
1691
+ // because it's a reserved JavaScript keyword.
1692
+ var real = {
1693
+ exec: RegExp.prototype.exec,
1694
+ match: String.prototype.match,
1695
+ replace: String.prototype.replace,
1696
+ split: String.prototype.split
1697
+ },
1698
+ /* regex syntax parsing with support for all the necessary cross-
1699
+ browser and context issues (escapings, character classes, etc.) */
1700
+ lib = {
1701
+ part: /(?:[^\\([#\s.]+|\\(?!k<[\w$]+>|[pP]{[^}]+})[\S\s]?|\((?=\?(?!#|<[\w$]+>)))+|(\()(?:\?(?:(#)[^)]*\)|<([$\w]+)>))?|\\(?:k<([\w$]+)>|[pP]{([^}]+)})|(\[\^?)|([\S\s])/g,
1702
+ replaceVar: /(?:[^$]+|\$(?![1-9$&`']|{[$\w]+}))+|\$(?:([1-9]\d*|[$&`'])|{([$\w]+)})/g,
1703
+ extended: /^(?:\s+|#.*)+/,
1704
+ quantifier: /^(?:[?*+]|{\d+(?:,\d*)?})/,
1705
+ classLeft: /&&\[\^?/g,
1706
+ classRight: /]/g
1707
+ },
1708
+ indexOf = function (array, item, from) {
1709
+ for (var i = from || 0; i < array.length; i++)
1710
+ if (array[i] === item) return i;
1711
+ return -1;
1712
+ },
1713
+ brokenExecUndef = /()??/.exec("")[1] !== undefined,
1714
+ plugins = {};
1715
+
1716
+ /**
1717
+ * Accepts a pattern and flags, returns a new, extended RegExp object.
1718
+ * differs from a native regex in that additional flags and syntax are
1719
+ * supported and browser inconsistencies are ameliorated.
1720
+ * @ignore
1721
+ */
1722
+ XRegExp = function (pattern, flags) {
1723
+ if (pattern instanceof RegExp) {
1724
+ if (flags !== undefined)
1725
+ throw TypeError("can't supply flags when constructing one RegExp from another");
1726
+ return pattern.addFlags(); // new copy
1727
+ }
1728
+
1729
+ var flags = flags || "",
1730
+ singleline = flags.indexOf("s") > -1,
1731
+ extended = flags.indexOf("x") > -1,
1732
+ hasNamedCapture = false,
1733
+ captureNames = [],
1734
+ output = [],
1735
+ part = lib.part,
1736
+ match, cc, len, index, regex;
1737
+
1738
+ part.lastIndex = 0; // in case the last XRegExp compilation threw an error (unbalanced character class)
1739
+
1740
+ while (match = real.exec.call(part, pattern)) {
1741
+ // comment pattern. this check must come before the capturing group check,
1742
+ // because both match[1] and match[2] will be non-empty.
1743
+ if (match[2]) {
1744
+ // keep tokens separated unless the following token is a quantifier
1745
+ if (!lib.quantifier.test(pattern.slice(part.lastIndex)))
1746
+ output.push("(?:)");
1747
+ // capturing group
1748
+ } else if (match[1]) {
1749
+ captureNames.push(match[3] || null);
1750
+ if (match[3])
1751
+ hasNamedCapture = true;
1752
+ output.push("(");
1753
+ // named backreference
1754
+ } else if (match[4]) {
1755
+ index = indexOf(captureNames, match[4]);
1756
+ // keep backreferences separate from subsequent literal numbers
1757
+ // preserve backreferences to named groups that are undefined at this point as literal strings
1758
+ output.push(index > -1 ?
1759
+ "\\" + (index + 1) + (isNaN(pattern.charAt(part.lastIndex)) ? "" : "(?:)") :
1760
+ match[0]
1761
+ );
1762
+ // unicode element (requires plugin)
1763
+ } else if (match[5]) {
1764
+ output.push(plugins.unicode ?
1765
+ plugins.unicode.get(match[5], match[0].charAt(1) === "P") :
1766
+ match[0]
1767
+ );
1768
+ // character class opening delimiter ("[" or "[^")
1769
+ // (non-native unicode elements are not supported within character classes)
1770
+ } else if (match[6]) {
1771
+ if (pattern.charAt(part.lastIndex) === "]") {
1772
+ // for cross-browser compatibility with ECMA-262 v3 behavior,
1773
+ // convert [] to (?!) and [^] to [\S\s].
1774
+ output.push(match[6] === "[" ? "(?!)" : "[\\S\\s]");
1775
+ part.lastIndex++;
1776
+ } else {
1777
+ // parse the character class with support for inner escapes and
1778
+ // ES4's infinitely nesting intersection syntax ([&&[^&&[]]]).
1779
+ cc = XRegExp.matchRecursive("&&" + pattern.slice(match.index), lib.classLeft, lib.classRight, "", {escapeChar: "\\"})[0];
1780
+ output.push(match[6] + cc + "]");
1781
+ part.lastIndex += cc.length + 1;
1782
+ }
1783
+ // dot ("."), pound sign ("#"), or whitespace character
1784
+ } else if (match[7]) {
1785
+ if (singleline && match[7] === ".") {
1786
+ output.push("[\\S\\s]");
1787
+ } else if (extended && lib.extended.test(match[7])) {
1788
+ len = real.exec.call(lib.extended, pattern.slice(part.lastIndex - 1))[0].length;
1789
+ // keep tokens separated unless the following token is a quantifier
1790
+ if (!lib.quantifier.test(pattern.slice(part.lastIndex - 1 + len)))
1791
+ output.push("(?:)");
1792
+ part.lastIndex += len - 1;
1793
+ } else {
1794
+ output.push(match[7]);
1795
+ }
1796
+ } else {
1797
+ output.push(match[0]);
1798
+ }
1799
+ }
1800
+
1801
+ regex = RegExp(output.join(""), real.replace.call(flags, /[sx]+/g, ""));
1802
+ regex._x = {
1803
+ source: pattern,
1804
+ captureNames: hasNamedCapture ? captureNames : null
1805
+ };
1806
+ return regex;
1807
+ };
1808
+
1809
+ /**
1810
+ * Barebones plugin support for now (intentionally undocumented)
1811
+ * @ignore
1812
+ * @param {Object} name
1813
+ * @param {Object} o
1814
+ */
1815
+ XRegExp.addPlugin = function (name, o) {
1816
+ plugins[name] = o;
1817
+ };
1818
+
1819
+ /**
1820
+ * Adds named capture support, with values returned as ``result.name``.
1821
+ *
1822
+ * Also fixes two cross-browser issues, following the ECMA-262 v3 spec:
1823
+ * - captured values for non-participating capturing groups should be returned
1824
+ * as ``undefined``, rather than the empty string.
1825
+ * - the regex's ``lastIndex`` should not be incremented after zero-length
1826
+ * matches.
1827
+ * @ignore
1828
+ */
1829
+ RegExp.prototype.exec = function (str) {
1830
+ var match = real.exec.call(this, str),
1831
+ name, i, r2;
1832
+ if (match) {
1833
+ // fix browsers whose exec methods don't consistently return
1834
+ // undefined for non-participating capturing groups
1835
+ if (brokenExecUndef && match.length > 1) {
1836
+ // r2 doesn't need /g or /y, but they shouldn't hurt
1837
+ r2 = new RegExp("^" + this.source + "$(?!\\s)", this.getNativeFlags());
1838
+ real.replace.call(match[0], r2, function () {
1839
+ for (i = 1; i < arguments.length - 2; i++) {
1840
+ if (arguments[i] === undefined) match[i] = undefined;
1841
+ }
1842
+ });
1843
+ }
1844
+ // attach named capture properties
1845
+ if (this._x && this._x.captureNames) {
1846
+ for (i = 1; i < match.length; i++) {
1847
+ name = this._x.captureNames[i - 1];
1848
+ if (name) match[name] = match[i];
1849
+ }
1850
+ }
1851
+ // fix browsers that increment lastIndex after zero-length matches
1852
+ if (this.global && this.lastIndex > (match.index + match[0].length))
1853
+ this.lastIndex--;
1854
+ }
1855
+ return match;
1856
+ };
1857
+ })(); // end anonymous function
1858
+ } // end if(!window.XRegExp)
1859
+
1860
+ /**
1861
+ * intentionally undocumented
1862
+ * @ignore
1863
+ */
1864
+ RegExp.prototype.getNativeFlags = function () {
1865
+ return (this.global ? "g" : "") +
1866
+ (this.ignoreCase ? "i" : "") +
1867
+ (this.multiline ? "m" : "") +
1868
+ (this.extended ? "x" : "") +
1869
+ (this.sticky ? "y" : "");
1870
+ };
1871
+
1872
+ /**
1873
+ * Accepts flags; returns a new XRegExp object generated by recompiling
1874
+ * the regex with the additional flags (may include non-native flags).
1875
+ * The original regex object is not altered.
1876
+ * @ignore
1877
+ */
1878
+ RegExp.prototype.addFlags = function (flags) {
1879
+ var regex = new XRegExp(this.source, (flags || "") + this.getNativeFlags());
1880
+ if (this._x) {
1881
+ regex._x = {
1882
+ source: this._x.source,
1883
+ captureNames: this._x.captureNames ? this._x.captureNames.slice(0) : null
1884
+ };
1885
+ }
1886
+ return regex;
1887
+ };
1888
+
1889
+ /**
1890
+ * Accepts a context object and string; returns the result of calling
1891
+ * ``exec`` with the provided string. the context is ignored but is
1892
+ * accepted for congruity with ``Function.prototype.call``.
1893
+ * @ignore
1894
+ */
1895
+ RegExp.prototype.call = function (context, str) {
1896
+ return this.exec(str);
1897
+ };
1898
+
1899
+ /**
1900
+ * Accepts a context object and arguments array; returns the result of
1901
+ * calling ``exec`` with the first value in the arguments array. the context
1902
+ * is ignored but is accepted for congruity with ``Function.prototype.apply``.
1903
+ * @ignore
1904
+ */
1905
+ RegExp.prototype.apply = function (context, args) {
1906
+ return this.exec(args[0]);
1907
+ };
1908
+
1909
+ /**
1910
+ * Accepts a pattern and flags; returns an XRegExp object. if the pattern
1911
+ * and flag combination has previously been cached, the cached copy is
1912
+ * returned, otherwise the new object is cached.
1913
+ * @ignore
1914
+ */
1915
+ XRegExp.cache = function (pattern, flags) {
1916
+ var key = "/" + pattern + "/" + (flags || "");
1917
+ return XRegExp.cache[key] || (XRegExp.cache[key] = new XRegExp(pattern, flags));
1918
+ };
1919
+
1920
+ /**
1921
+ * Accepts a string; returns the string with regex metacharacters escaped.
1922
+ * the returned string can safely be used within a regex to match a literal
1923
+ * string. escaped characters are [, ], {, }, (, ), -, *, +, ?, ., \, ^, $,
1924
+ * |, #, [comma], and whitespace.
1925
+ * @ignore
1926
+ */
1927
+ XRegExp.escape = function (str) {
1928
+ return str.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, "\\$&");
1929
+ };
1930
+
1931
+ /**
1932
+ * Accepts a string to search, left and right delimiters as regex pattern
1933
+ * strings, optional regex flags (may include non-native s, x, and y flags),
1934
+ * and an options object which allows setting an escape character and changing
1935
+ * the return format from an array of matches to a two-dimensional array of
1936
+ * string parts with extended position data. returns an array of matches
1937
+ * (optionally with extended data), allowing nested instances of left and right
1938
+ * delimiters. use the g flag to return all matches, otherwise only the first
1939
+ * is returned. if delimiters are unbalanced within the subject data, an error
1940
+ * is thrown.
1941
+ *
1942
+ * This function admittedly pushes the boundaries of what can be accomplished
1943
+ * sensibly without a "real" parser. however, by doing so it provides flexible
1944
+ * and powerful recursive parsing capabilities with minimal code weight.
1945
+ *
1946
+ * Warning: the ``escapeChar`` option is considered experimental and might be
1947
+ * changed or removed in future versions of XRegExp.
1948
+ *
1949
+ * unsupported features:
1950
+ * - backreferences within delimiter patterns when using ``escapeChar``.
1951
+ * - although providing delimiters as regex objects adds the minor feature of
1952
+ * independent delimiter flags, it introduces other limitations and is only
1953
+ * intended to be done by the ``XRegExp`` constructor (which can't call
1954
+ * itself while building a regex).
1955
+ *
1956
+ * @ignore
1957
+ */
1958
+ XRegExp.matchRecursive = function (str, left, right, flags, options) {
1959
+ var options = options || {},
1960
+ escapeChar = options.escapeChar,
1961
+ vN = options.valueNames,
1962
+ flags = flags || "",
1963
+ global = flags.indexOf("g") > -1,
1964
+ ignoreCase = flags.indexOf("i") > -1,
1965
+ multiline = flags.indexOf("m") > -1,
1966
+ sticky = flags.indexOf("y") > -1,
1967
+ /* sticky mode has its own handling in this function, which means you
1968
+ can use flag "y" even in browsers which don't support it natively */
1969
+ flags = flags.replace(/y/g, ""),
1970
+ left = left instanceof RegExp ? (left.global ? left : left.addFlags("g")) : new XRegExp(left, "g" + flags),
1971
+ right = right instanceof RegExp ? (right.global ? right : right.addFlags("g")) : new XRegExp(right, "g" + flags),
1972
+ output = [],
1973
+ openTokens = 0,
1974
+ delimStart = 0,
1975
+ delimEnd = 0,
1976
+ lastOuterEnd = 0,
1977
+ outerStart, innerStart, leftMatch, rightMatch, escaped, esc;
1978
+
1979
+ if (escapeChar) {
1980
+ if (escapeChar.length > 1) throw SyntaxError("can't supply more than one escape character");
1981
+ if (multiline) throw TypeError("can't supply escape character when using the multiline flag");
1982
+ escaped = XRegExp.escape(escapeChar);
1983
+ /* Escape pattern modifiers:
1984
+ /g - not needed here
1985
+ /i - included
1986
+ /m - **unsupported**, throws error
1987
+ /s - handled by XRegExp when delimiters are provided as strings
1988
+ /x - handled by XRegExp when delimiters are provided as strings
1989
+ /y - not needed here; supported by other handling in this function
1990
+ */
1991
+ esc = new RegExp(
1992
+ "^(?:" + escaped + "[\\S\\s]|(?:(?!" + left.source + "|" + right.source + ")[^" + escaped + "])+)+",
1993
+ ignoreCase ? "i" : ""
1994
+ );
1995
+ }
1996
+
1997
+ while (true) {
1998
+ /* advance the starting search position to the end of the last delimiter match.
1999
+ a couple special cases are also covered:
2000
+ - if using an escape character, advance to the next delimiter's starting position,
2001
+ skipping any escaped characters
2002
+ - first time through, reset lastIndex in case delimiters were provided as regexes
2003
+ */
2004
+ left.lastIndex = right.lastIndex = delimEnd +
2005
+ (escapeChar ? (esc.exec(str.slice(delimEnd)) || [""])[0].length : 0);
2006
+
2007
+ leftMatch = left.exec(str);
2008
+ rightMatch = right.exec(str);
2009
+
2010
+ // only keep the result which matched earlier in the string
2011
+ if (leftMatch && rightMatch) {
2012
+ if (leftMatch.index <= rightMatch.index)
2013
+ rightMatch = null;
2014
+ else leftMatch = null;
2015
+ }
2016
+
2017
+ /* paths*:
2018
+ leftMatch | rightMatch | openTokens | result
2019
+ 1 | 0 | 1 | ...
2020
+ 1 | 0 | 0 | ...
2021
+ 0 | 1 | 1 | ...
2022
+ 0 | 1 | 0 | throw
2023
+ 0 | 0 | 1 | throw
2024
+ 0 | 0 | 0 | break
2025
+ * - does not include the sticky mode special case
2026
+ - the loop ends after the first completed match if not in global mode
2027
+ */
2028
+
2029
+ if (leftMatch || rightMatch) {
2030
+ delimStart = (leftMatch || rightMatch).index;
2031
+ delimEnd = (leftMatch ? left : right).lastIndex;
2032
+ } else if (!openTokens) {
2033
+ break;
2034
+ }
2035
+
2036
+ if (sticky && !openTokens && delimStart > lastOuterEnd)
2037
+ break;
2038
+
2039
+ if (leftMatch) {
2040
+ if (!openTokens++) {
2041
+ outerStart = delimStart;
2042
+ innerStart = delimEnd;
2043
+ }
2044
+ } else if (rightMatch && openTokens) {
2045
+ if (!--openTokens) {
2046
+ if (vN) {
2047
+ if (vN[0] && outerStart > lastOuterEnd)
2048
+ output.push([vN[0], str.slice(lastOuterEnd, outerStart), lastOuterEnd, outerStart]);
2049
+ if (vN[1]) output.push([vN[1], str.slice(outerStart, innerStart), outerStart, innerStart]);
2050
+ if (vN[2]) output.push([vN[2], str.slice(innerStart, delimStart), innerStart, delimStart]);
2051
+ if (vN[3]) output.push([vN[3], str.slice(delimStart, delimEnd), delimStart, delimEnd]);
2052
+ } else {
2053
+ output.push(str.slice(innerStart, delimStart));
2054
+ }
2055
+ lastOuterEnd = delimEnd;
2056
+ if (!global)
2057
+ break;
2058
+ }
2059
+ } else {
2060
+ // reset lastIndex in case delimiters were provided as regexes
2061
+ left.lastIndex = right.lastIndex = 0;
2062
+ throw Error("subject data contains unbalanced delimiters");
2063
+ }
2064
+
2065
+ // if the delimiter matched an empty string, advance delimEnd to avoid an infinite loop
2066
+ if (delimStart === delimEnd)
2067
+ delimEnd++;
2068
+ }
2069
+
2070
+ if (global && !sticky && vN && vN[0] && str.length > lastOuterEnd)
2071
+ output.push([vN[0], str.slice(lastOuterEnd), lastOuterEnd, str.length]);
2072
+
2073
+ // reset lastIndex in case delimiters were provided as regexes
2074
+ left.lastIndex = right.lastIndex = 0;
2075
+
2076
+ return output;
2077
+ };
2078
+ /**
2079
+ * SyntaxHighlighter
2080
+ * http://alexgorbatchev.com/
2081
+ *
2082
+ * SyntaxHighlighter is donationware. If you are using it, please donate.
2083
+ * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate
2084
+ *
2085
+ * @version
2086
+ * 2.0.320 (May 03 2009)
2087
+ *
2088
+ * @copyright
2089
+ * Copyright (C) 2004-2009 Alex Gorbatchev.
2090
+ *
2091
+ * @license
2092
+ * This file is part of SyntaxHighlighter.
2093
+ *
2094
+ * SyntaxHighlighter is free software: you can redistribute it and/or modify
2095
+ * it under the terms of the GNU Lesser General Public License as published by
2096
+ * the Free Software Foundation, either version 3 of the License, or
2097
+ * (at your option) any later version.
2098
+ *
2099
+ * SyntaxHighlighter is distributed in the hope that it will be useful,
2100
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2101
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2102
+ * GNU General Public License for more details.
2103
+ *
2104
+ * You should have received a copy of the GNU General Public License
2105
+ * along with SyntaxHighlighter. If not, see <http://www.gnu.org/copyleft/lesser.html>.
2106
+ */
2107
+ SyntaxHighlighter.brushes.Xml = function()
2108
+ {
2109
+ function process(match, regexInfo)
2110
+ {
2111
+ var constructor = SyntaxHighlighter.Match,
2112
+ code = match[0],
2113
+ tag = new XRegExp('(&lt;|<)[\\s\\/\\?]*(?<name>[:\\w-\\.]+)', 'xg').exec(code),
2114
+ result = []
2115
+ ;
2116
+
2117
+ if (match.attributes != null)
2118
+ {
2119
+ var attributes,
2120
+ regex = new XRegExp('(?<name> [\\w:\\-\\.]+)' +
2121
+ '\\s*=\\s*' +
2122
+ '(?<value> ".*?"|\'.*?\'|\\w+)',
2123
+ 'xg');
2124
+
2125
+ while ((attributes = regex.exec(code)) != null)
2126
+ {
2127
+ result.push(new constructor(attributes.name, match.index + attributes.index, 'color1'));
2128
+ result.push(new constructor(attributes.value, match.index + attributes.index + attributes[0].indexOf(attributes.value), 'string'));
2129
+ }
2130
+ }
2131
+
2132
+ if (tag != null)
2133
+ result.push(
2134
+ new constructor(tag.name, match.index + tag[0].indexOf(tag.name), 'keyword')
2135
+ );
2136
+
2137
+ return result;
2138
+ }
2139
+
2140
+ this.regexList = [
2141
+ { regex: new XRegExp('(\\&lt;|<)\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\](\\&gt;|>)', 'gm'), css: 'color2' }, // <![ ... [ ... ]]>
2142
+ { regex: new XRegExp('(\\&lt;|<)!--\\s*.*?\\s*--(\\&gt;|>)', 'gm'), css: 'comments' }, // <!-- ... -->
2143
+ { regex: new XRegExp('(&lt;|<)[\\s\\/\\?]*(\\w+)(?<attributes>.*?)[\\s\\/\\?]*(&gt;|>)', 'sg'), func: process }
2144
+ ];
2145
+ };
2146
+
2147
+ SyntaxHighlighter.brushes.Xml.prototype = new SyntaxHighlighter.Highlighter();
2148
+ SyntaxHighlighter.brushes.Xml.aliases = ['xml', 'xhtml', 'xslt', 'html', 'xhtml'];
2149
+ /**
2150
+ * SyntaxHighlighter
2151
+ * http://alexgorbatchev.com/
2152
+ *
2153
+ * SyntaxHighlighter is donationware. If you are using it, please donate.
2154
+ * http://alexgorbatchev.com/wiki/SyntaxHighlighter:Donate
2155
+ *
2156
+ * @version
2157
+ * 2.0.320 (May 03 2009)
2158
+ *
2159
+ * @copyright
2160
+ * Copyright (C) 2004-2009 Alex Gorbatchev.
2161
+ *
2162
+ * @license
2163
+ * This file is part of SyntaxHighlighter.
2164
+ *
2165
+ * SyntaxHighlighter is free software: you can redistribute it and/or modify
2166
+ * it under the terms of the GNU Lesser General Public License as published by
2167
+ * the Free Software Foundation, either version 3 of the License, or
2168
+ * (at your option) any later version.
2169
+ *
2170
+ * SyntaxHighlighter is distributed in the hope that it will be useful,
2171
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2172
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2173
+ * GNU General Public License for more details.
2174
+ *
2175
+ * You should have received a copy of the GNU General Public License
2176
+ * along with SyntaxHighlighter. If not, see <http://www.gnu.org/copyleft/lesser.html>.
2177
+ */
2178
+ SyntaxHighlighter.brushes.JScript = function()
2179
+ {
2180
+ var keywords = 'break case catch continue ' +
2181
+ 'default delete do else false ' +
2182
+ 'for function if in instanceof ' +
2183
+ 'new null return super switch ' +
2184
+ 'this throw true try typeof var while with'
2185
+ ;
2186
+
2187
+ this.regexList = [
2188
+ { regex: SyntaxHighlighter.regexLib.singleLineCComments, css: 'comments' }, // one line comments
2189
+ { regex: SyntaxHighlighter.regexLib.multiLineCComments, css: 'comments' }, // multiline comments
2190
+ { regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'string' }, // double quoted strings
2191
+ { regex: SyntaxHighlighter.regexLib.singleQuotedString, css: 'string' }, // single quoted strings
2192
+ { regex: /\s*#.*/gm, css: 'preprocessor' }, // preprocessor tags like #region and #endregion
2193
+ { regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword' } // keywords
2194
+ ];
2195
+
2196
+ this.forHtmlScript(SyntaxHighlighter.regexLib.scriptScriptTags);
2197
+ };
2198
+
2199
+ SyntaxHighlighter.brushes.JScript.prototype = new SyntaxHighlighter.Highlighter();
2200
+ SyntaxHighlighter.brushes.JScript.aliases = ['js', 'jscript', 'javascript'];
2201
+
2202
+
2203
+ SyntaxHighlighter.config.clipboardSwf = 'syntax/clipboard.swf';
2204
+ $(function () {
2205
+ var divs = $([]);
2206
+ $("#container .source").each(function () {
2207
+ var code = $(this).html().replace(/</g,'&lt;').replace(/>/g,'&gt;'),
2208
+ div = $('<div class="code"><pre class="brush:' + ( $(this).is("script") ? 'js' : 'xml' ) + ';">' + code + '</pre></div>'),
2209
+ demo = $(this).prevAll(".demo:eq(0)");
2210
+ $(this).after(div);
2211
+ divs = divs.add(div);
2212
+ });
2213
+ SyntaxHighlighter.all();
2214
+
2215
+ setTimeout((function (divs) {
2216
+ return function () {
2217
+ divs.each(function () {
2218
+ var div = $(this),
2219
+ demo = $(this).prevAll(".demo:eq(0)"),
2220
+ h = false;
2221
+ var h = Math.max(demo[0].offsetHeight, div[0].offsetHeight);
2222
+ if(h) {
2223
+ if(h < 198) h = 198;
2224
+ div.height(h);
2225
+ demo.height(h);
2226
+ }
2227
+ });
2228
+ }
2229
+ })(divs), 500);
2230
+
2231
+ // $(".panel").hide().prev().click(function () { $(this).next().toggle(); }).css("cursor","pointer");
2232
+ });