capitate 0.2.11 → 0.2.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/History.txt +9 -0
  2. data/Manifest.txt +11 -1
  3. data/lib/capitate/cap_ext/connections.rb +15 -8
  4. data/lib/capitate/cap_ext/run_via.rb +2 -0
  5. data/lib/capitate/cap_ext/variables.rb +9 -2
  6. data/lib/capitate/plugins/base.rb +17 -12
  7. data/lib/capitate/plugins/build.rb +14 -11
  8. data/lib/capitate/plugins/prompt.rb +6 -8
  9. data/lib/capitate/plugins/script.rb +6 -4
  10. data/lib/capitate/plugins/templates.rb +16 -7
  11. data/lib/capitate/plugins/upload.rb +2 -1
  12. data/lib/capitate/plugins/utils.rb +7 -5
  13. data/lib/capitate/task_node.rb +30 -32
  14. data/lib/capitate/version.rb +1 -1
  15. data/lib/recipes/backgroundrb.rb +18 -4
  16. data/lib/recipes/centos/backgroundrb.rb +10 -3
  17. data/lib/recipes/centos/centos.rb +21 -8
  18. data/lib/recipes/centos/imagemagick.rb +4 -1
  19. data/lib/recipes/centos/memcached.rb +26 -8
  20. data/lib/recipes/centos/mongrel_cluster.rb +33 -13
  21. data/lib/recipes/centos/monit.rb +32 -11
  22. data/lib/recipes/centos/mysql.rb +7 -2
  23. data/lib/recipes/centos/nginx.rb +29 -10
  24. data/lib/recipes/centos/ruby.rb +11 -2
  25. data/lib/recipes/centos/sphinx.rb +32 -10
  26. data/lib/recipes/docs.rb +12 -7
  27. data/lib/recipes/logrotate/backgroundrb.rb +25 -0
  28. data/lib/recipes/logrotated.rb +18 -12
  29. data/lib/recipes/memcached.rb +0 -25
  30. data/lib/recipes/monit/backgroundrb.rb +39 -0
  31. data/lib/recipes/monit/memcached.rb +22 -0
  32. data/lib/recipes/{mongrel_cluster.rb → monit/mongrel_cluster.rb} +22 -12
  33. data/lib/recipes/monit/mysql.rb +21 -0
  34. data/lib/recipes/monit/nginx.rb +34 -0
  35. data/lib/recipes/monit/sphinx.rb +29 -0
  36. data/lib/recipes/monit/sshd.rb +27 -0
  37. data/lib/recipes/monit.rb +18 -3
  38. data/lib/recipes/mysql.rb +22 -32
  39. data/lib/recipes/nginx.rb +15 -30
  40. data/lib/recipes/rails.rb +17 -6
  41. data/lib/recipes/sphinx.rb +11 -24
  42. data/lib/recipes/sshd.rb +4 -22
  43. data/lib/recipes/syslogd.rb +4 -0
  44. data/lib/templates/backgroundrb/backgroundrb.monitrc.erb +4 -0
  45. data/lib/templates/backgroundrb/backgroundrb.yml.erb +4 -0
  46. data/website/index.html +10 -2
  47. data/website/javascripts/code_highlighter.js +188 -0
  48. data/website/javascripts/ruby.js +18 -0
  49. data/website/stylesheets/screen.css +116 -23
  50. data/website/template.rhtml +9 -1
  51. data/website/template_recipe.rhtml +12 -1
  52. metadata +13 -3
@@ -0,0 +1,27 @@
1
+ namespace :sshd do
2
+
3
+ namespace :monit do
4
+
5
+ desc <<-DESC
6
+ Install sshd monit hooks.
7
+
8
+ *sshd_port*: SSH daemon port. _Defaults to 22_\n
9
+ *sshd_pid_path*: Path to mysql pid file. _Defaults to /var/run/sshd.pid_\n
10
+ *monit_conf_dir*: Destination for monitrc. _Defaults to "/etc/monit"_\n
11
+
12
+ "Source":#{link_to_source(__FILE__)}
13
+ DESC
14
+ task :install do
15
+
16
+ # Settings
17
+ fetch_or_default(:sshd_port, 3306)
18
+ fetch_or_default(:sshd_pid_path, "/var/run/sshd.pid")
19
+ fetch_or_default(:monit_conf_dir, "/etc/monit")
20
+
21
+ put template.load("sshd/sshd.monitrc.erb", binding), "/tmp/sshd.monitrc"
22
+ run_via "install -o root /tmp/sshd.monitrc #{monit_conf_dir}/sshd.monitrc"
23
+ end
24
+
25
+ end
26
+
27
+ end
data/lib/recipes/monit.rb CHANGED
@@ -5,7 +5,12 @@ namespace :monit do
5
5
 
6
6
  HUP's the process from the pid file, if it exists.
7
7
 
8
- *monit_pid_path*: Path to monit pid file. _Defaults to <tt>/var/run/monit.pid</tt>_
8
+ <dl>
9
+ <dt>monit_pid_path</dt>
10
+ <dd>Path to monit pid file</dd>
11
+ <dd class="default">Defaults to @/var/run/monit.pid@</dd>
12
+ </dl>
13
+ "Source":#{link_to_source(__FILE__)}
9
14
  DESC
10
15
  task :restart do
11
16
  fetch_or_default(:monit_pid_path, "/var/run/monit.pid")
@@ -17,7 +22,12 @@ namespace :monit do
17
22
  desc <<-DESC
18
23
  Unmonitor all.
19
24
 
20
- *monit_bin_path*: Path to monit bin. _Defaults to <tt>monit</tt>_
25
+ <dl>
26
+ <dt>monit_bin_path</dt>
27
+ <dd>Path to monit bin.</dd>
28
+ <dd>Defaults to @monit@</dd>
29
+ </dl>
30
+ "Source":#{link_to_source(__FILE__)}
21
31
  DESC
22
32
  task :unmonitor_all do
23
33
  fetch_or_default(:monit_bin_path, "monit")
@@ -28,7 +38,12 @@ namespace :monit do
28
38
  desc <<-DESC
29
39
  Monitor all.
30
40
 
31
- *monit_bin_path*: Path to monit bin. _Defaults to <tt>monit</tt>_
41
+ <dl>
42
+ <dt>monit_bin_path</dt>
43
+ <dd>Path to monit bin.</dd>
44
+ <dd>Defaults to @monit@</dd>
45
+ </dl>
46
+ "Source":#{link_to_source(__FILE__)}
32
47
  DESC
33
48
  task :monitor_all do
34
49
  fetch_or_default(:monit_bin_path, "monit")
data/lib/recipes/mysql.rb CHANGED
@@ -1,42 +1,32 @@
1
1
  # Mysql recipes
2
2
  namespace :mysql do
3
3
 
4
- namespace :monit do
4
+ desc <<-DESC
5
+ Create database, database user, and set grant permissions.
5
6
 
6
- desc <<-DESC
7
- Install mysql monit hooks.
7
+ <dl>
8
+ <dt>db_name</dt>
9
+ <dd>Database name (application).</dd>
8
10
 
9
- *mysql_port*: Mysql port. _Defaults to 3306_\n
10
- *mysql_pid_path*: Path to mysql pid file. _Defaults to /var/run/mysqld/mysqld.pid_\n
11
- @set :mysql_pid_path, "/var/run/mysqld/mysqld.pid"@\n
12
- *monit_conf_dir*: Destination for monitrc. _Defaults to "/etc/monit"_\n
13
- @set :monit_conf_dir, "/etc/monit"@\n
14
- DESC
15
- task :install do
16
-
17
- # Settings
18
- fetch_or_default(:mysql_pid_path, "/var/run/mysqld/mysqld.pid")
19
- fetch_or_default(:mysql_port, 3306)
20
- fetch_or_default(:monit_conf_dir, "/etc/monit")
21
-
22
- put template.load("mysql/mysql.monitrc.erb", binding), "/tmp/mysql.monitrc"
23
- run_via "install -o root /tmp/mysql.monitrc #{monit_conf_dir}/mysql.monitrc"
24
- end
25
-
26
- end
11
+ <dt>db_user</dt>
12
+ <dd>Database user (application).</dd>
27
13
 
28
- desc <<-DESC
29
- Create database, database user, and set grant permissions.
14
+ <dt>db_pass</dt>
15
+ <dd>Database password (application).</dd>
16
+
17
+ <dt>mysql_grant_locations</dt>
18
+ <dd>Grant locations. </dd>
19
+ <dd>Defaults to @[ "localhost" ]@</dd>
20
+
21
+ <dt>mysql_grant_priv_type</dt>
22
+ <dd>Grant privilege types.</dd>
23
+ <dd>Defaults to @ALL@</dd>
30
24
 
31
- *db_name*: Database name (application).\n
32
- *db_user*: Database user (application).\n
33
- *db_pass*: Database password (application).\n
34
- *mysql_grant_locations*: Grant locations. _Defaults to localhost_\n
35
- @set :mysql_grant_locations, [ "localhost", "192.168.1.111" ]@\n
36
- *mysql_grant_priv_type*: Grant privilege types. _Defaults to ALL_\n
37
- @set :mysql_grant_priv_type, "ALL"@\n
38
- *mysql_admin_password*: Mysql admin password (to use to connect). Defaults to password prompt.\n
39
- @set :mysql_admin_password, prompt.password('Mysql admin password: '))@
25
+ <dt>mysql_admin_password</dt>
26
+ <dd>Mysql admin password (to use to connect).</dd>
27
+ <dd>Defaults to password prompt.</dd>
28
+ </dl>
29
+ "Source":#{link_to_source(__FILE__)}
40
30
  DESC
41
31
  task :setup, :roles => :db do
42
32
 
data/lib/recipes/nginx.rb CHANGED
@@ -1,40 +1,25 @@
1
1
  # Nginx recipes
2
2
  namespace :nginx do
3
3
 
4
- namespace :monit do
5
-
6
- desc <<-DESC
7
- Install nginx monit hooks.
8
-
9
- *nginx_pid_path*: Path to nginx pid file. _Defaults to /var/run/nginx.pid_\n
10
- @set :nginx_pid_path, "/var/run/nginx.pid"@\n
11
- *monit_conf_dir*: Destination for monitrc. _Defaults to "/etc/monit"_\n
12
- @set :monit_conf_dir, "/etc/monit"@\n
13
- DESC
14
- task :install do
15
-
16
- # Settings
17
- fetch_or_default(:nginx_pid_path, "/var/run/nginx.pid")
18
- fetch_or_default(:monit_conf_dir, "/etc/monit")
19
-
20
- put template.load("nginx/nginx.monitrc.erb", binding), "/tmp/nginx.monitrc"
21
- run_via "install -o root /tmp/nginx.monitrc #{monit_conf_dir}/nginx.monitrc"
22
- end
23
-
24
- end
25
-
26
4
  namespace :mongrel do
27
5
  desc <<-DESC
28
6
  Generate the nginx vhost include (for a mongrel setup).
29
7
 
30
- *mongrel_application*: Mongrel application. _Defaults to <tt>:application</tt>_
31
- *mongrel_size*: Number of mongrels.\n
32
- @set :mongrel_size, 3@\n
33
- *mongrel_port*: Starting port for mongrels.\n
34
- If there are 3 mongrels with port 9000, then instances will be at 9000, 9001, and 9002\n
35
- @set :mongrel_port, 9000@\n
36
- *domain_name*: Domain name for nginx virtual host, (without www prefix).\n
37
- @set :domain_name, "foo.com"@
8
+ <dl>
9
+ <dt>mongrel_application</dt>
10
+ <dd>Mongrel application. _Defaults to <tt>:application</tt>_
11
+
12
+ <dt>mongrel_size</dt>: Number of mongrels.\n
13
+ <dd>@set :mongrel_size, 3@\n
14
+
15
+ <dt>*mongrel_port</dt>
16
+ <dd>Starting port for mongrels. If there are 3 mongrels with port 9000, then instances will be at 9000, 9001, and 9002</dd>
17
+ <dd>@set :mongrel_port, 9000@</dd>
18
+
19
+ <dt>domain_name</dt>: Domain name for nginx virtual host, (without www prefix).</dd>
20
+ <dd>@set :domain_name, "foo.com"@</dd>
21
+ </dl>
22
+ "Source":#{link_to_source(__FILE__)}
38
23
  DESC
39
24
  task :setup do
40
25
 
data/lib/recipes/rails.rb CHANGED
@@ -15,6 +15,8 @@ namespace :rails do
15
15
  *db_socket*: Database socket (can be nil, if you are using host). _Defaults to nil_\n
16
16
  @set :db_socket, "/var/lib/mysql/mysql.sock"@\n
17
17
  *database_yml_template*: Path to database yml erb template. _Defaults to <tt>rails/database.yml.erb</tt>_ (in this GEM)\n
18
+
19
+ "Source":#{link_to_source(__FILE__)}
18
20
  DESC
19
21
  task :setup, :roles => :app do
20
22
 
@@ -49,8 +51,11 @@ namespace :rails do
49
51
  namespace :logs do
50
52
 
51
53
  desc <<-DESC
52
- Tail production log files.\n
53
- http://errtheblog.com/posts/19-streaming-capistrano
54
+ Tail production log files.
55
+
56
+ "From errtheblog":http://errtheblog.com/posts/19-streaming-capistrano
57
+
58
+ "Source":#{link_to_source(__FILE__)}
54
59
  DESC
55
60
  task :tail, :roles => :web do
56
61
  run "tail -f #{shared_path}/log/production.log" do |channel, stream, data|
@@ -62,8 +67,11 @@ namespace :rails do
62
67
 
63
68
 
64
69
  desc <<-DESC
65
- Check production log files in TextMate.\n
66
- See http://errtheblog.com/posts/19-streaming-capistrano
70
+ Check production log files in TextMate.
71
+
72
+ "From errtheblog":http://errtheblog.com/posts/19-streaming-capistrano
73
+
74
+ "Source":#{link_to_source(__FILE__)}
67
75
  DESC
68
76
  task :mate, :roles => :app do
69
77
 
@@ -87,8 +95,11 @@ namespace :rails do
87
95
  end
88
96
 
89
97
  desc <<-DESC
90
- Remotely console.\n
91
- See http://errtheblog.com/posts/19-streaming-capistrano
98
+ Remotely console.
99
+
100
+ "From errtheblog":http://errtheblog.com/posts/19-streaming-capistrano
101
+
102
+ "Source":#{link_to_source(__FILE__)}
92
103
  DESC
93
104
  task :console, :roles => :app do
94
105
  input = ''
@@ -1,25 +1,6 @@
1
1
  # Sphinx recipes
2
2
  namespace :sphinx do
3
3
 
4
- namespace :monit do
5
-
6
- desc <<-DESC
7
- Create monit configuration for sphinx.\n
8
- *monit_conf_dir*: Destination for monitrc. _Defaults to "/etc/monit"_\n
9
- *sphinx_pid_path*: Location for sphinx pid. _Defaults to "[shared_path]/pids/searchd.pid"_\n
10
- DESC
11
- task :setup do
12
-
13
- # Settings
14
- fetch_or_default(:monit_conf_dir, "/etc/monit")
15
- fetch_or_default(:sphinx_pid_path, "#{shared_path}/pids/searchd.pid")
16
-
17
- put template.load("sphinx/sphinx.monitrc.erb"), "/tmp/sphinx_#{application}.monitrc"
18
- sudo "install -o root /tmp/sphinx_#{application}.monitrc #{monit_conf_dir}/sphinx_#{application}.monitrc"
19
- end
20
-
21
- end
22
-
23
4
  desc <<-DESC
24
5
  Update sphinx for application.
25
6
 
@@ -39,6 +20,7 @@ namespace :sphinx do
39
20
  *sphinx_db_host*: Sphinx DB host. _Defaults to db_host_\n
40
21
  *sphinx_conf_host*: Sphinx DB host to listen on. _Defaults to 127.0.0.1_\n
41
22
 
23
+ "Source":#{link_to_source(__FILE__)}
42
24
  DESC
43
25
  task :update_conf do
44
26
 
@@ -60,11 +42,18 @@ namespace :sphinx do
60
42
  put template.load(sphinx_conf_template), sphinx_conf_path
61
43
  end
62
44
 
45
+ desc "Make symlink for sphinx conf"
46
+ task :update_code do
47
+ run "ln -nfs #{shared_path}/config/sphinx.conf #{release_path}/config/sphinx.conf"
48
+ end
49
+
63
50
  desc <<-DESC
64
51
  Rotate sphinx index for application.
65
52
 
66
53
  *sphinx_prefix*: Location to sphinx install. _Defaults to nil_\n
67
54
  *sphinx_conf*: Location to sphinx conf. _Defaults to "[shared_path]/config/sphinx.conf"_\n
55
+
56
+ "Source":#{link_to_source(__FILE__)}
68
57
  DESC
69
58
  task :rotate_all do
70
59
  fetch_or_default(:sphinx_prefix, nil)
@@ -80,6 +69,8 @@ namespace :sphinx do
80
69
 
81
70
  *sphinx_prefix*: Location to sphinx install. _Defaults to nil_\n
82
71
  *sphinx_conf*: Location to sphinx conf. _Defaults to "[shared_path]/config/sphinx.conf"_\n
72
+
73
+ "Source":#{link_to_source(__FILE__)}
83
74
  DESC
84
75
  task :index_all do
85
76
  fetch_or_default(:sphinx_prefix, nil)
@@ -89,9 +80,5 @@ namespace :sphinx do
89
80
 
90
81
  run "#{indexer_path} --config #{sphinx_conf} --all"
91
82
  end
92
-
93
- desc "Restart sphinx"
94
- task :restart do
95
- sudo "/sbin/service monit restart sphinx_#{application}"
96
- end
83
+
97
84
  end
data/lib/recipes/sshd.rb CHANGED
@@ -1,32 +1,12 @@
1
1
  namespace :sshd do
2
2
 
3
- namespace :monit do
4
-
5
- desc <<-DESC
6
- Install sshd monit hooks.
7
-
8
- *sshd_port*: SSH daemon port. _Defaults to 22_\n
9
- *sshd_pid_path*: Path to mysql pid file. _Defaults to /var/run/sshd.pid_\n
10
- *monit_conf_dir*: Destination for monitrc. _Defaults to "/etc/monit"_\n
11
- DESC
12
- task :install do
13
-
14
- # Settings
15
- fetch_or_default(:sshd_port, 3306)
16
- fetch_or_default(:sshd_pid_path, "/var/run/sshd.pid")
17
- fetch_or_default(:monit_conf_dir, "/etc/monit")
18
-
19
- put template.load("sshd/sshd.monitrc.erb", binding), "/tmp/sshd.monitrc"
20
- run_via "install -o root /tmp/sshd.monitrc #{monit_conf_dir}/sshd.monitrc"
21
- end
22
-
23
- end
24
-
25
3
  desc <<-DESC
26
4
  Create public and private keys for ssh.
27
5
 
28
6
  *ssh_keygen_type*: SSH keygen type. _Defaults to rsa_\n
29
7
  *ssh_keygen_bits*: SSH keygen bits. _Defaults to 2048_\n
8
+
9
+ "Source":#{link_to_source(__FILE__)}
30
10
  DESC
31
11
  task :keygen do
32
12
  # Settings
@@ -56,6 +36,8 @@ namespace :sshd do
56
36
  Add to authorized keys. Uses <tt>.ssh/authorized_keys</tt>.
57
37
 
58
38
  *ssh_public_key*: The public key from ssh:keygen.
39
+
40
+ "Source":#{link_to_source(__FILE__)}
59
41
  DESC
60
42
  task :authorize_key do
61
43
 
@@ -6,6 +6,8 @@ namespace :syslogd do
6
6
  *syslog_program_name*: syslog program name. What you used for <tt>SyslogLogger.new("program_name_here")</tt>\n
7
7
  *syslog_log_path*: Path to log.\n
8
8
  *syslog_conf_path*: Path to syslog conf. _Defaults to <tt>/etc/syslog.conf</tt>_\n
9
+
10
+ "Source":#{link_to_source(__FILE__)}
9
11
  DESC
10
12
  task :setup_conf do
11
13
 
@@ -37,6 +39,8 @@ namespace :syslogd do
37
39
  *newsyslog_size*: Max size. _Defaults to *_\n
38
40
  *newsyslog_when*: When to rotate. _Defaults to @T00_\n
39
41
  *newsyslog_zb*: Whether to gzip or tarball. _Defaults to Z_\n
42
+
43
+ "Source":#{link_to_source(__FILE__)}
40
44
  DESC
41
45
  task :setup_newsyslog_conf do
42
46
 
@@ -0,0 +1,4 @@
1
+ check process backgroundrb_<%= application %> with pidfile <%= backgroundrb_pid_path %>
2
+ start program = "/sbin/service backgroundrb_<%= application %> start"
3
+ stop program = "/sbin/service backgroundrb_<%= application %> stop"
4
+ if failed host 127.0.0.1 port <%= backgroundrb_port %> then restart
@@ -8,3 +8,7 @@
8
8
  :development:
9
9
  :backgroundrb:
10
10
  :log: foreground
11
+
12
+ :production:
13
+ :backgroundrb:
14
+ :lazy_load: true
data/website/index.html CHANGED
@@ -38,7 +38,7 @@
38
38
 
39
39
  <div id="version" class="clickable box" onclick='document.location = "http://rubyforge.org/projects/capitate"; return false'>
40
40
  <p>Get Version</p>
41
- <a href="http://rubyforge.org/projects/capitate" class="numbers">0.2.11</a>
41
+ <a href="http://rubyforge.org/projects/capitate" class="numbers">0.2.13</a>
42
42
  </div>
43
43
 
44
44
  <div id="recipes">
@@ -143,7 +143,15 @@
143
143
  </p>
144
144
  </div>
145
145
 
146
- <!-- insert site tracking codes here, like Google Urchin -->
146
+ <script type="text/javascript">
147
+ var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
148
+ document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
149
+ </script>
150
+ <script type="text/javascript">
151
+ var pageTracker = _gat._getTracker("UA-1286493-6");
152
+ pageTracker._initData();
153
+ pageTracker._trackPageview();
154
+ </script>
147
155
 
148
156
  </body>
149
157
  </html>
@@ -0,0 +1,188 @@
1
+ /* Unobtrustive Code Highlighter By Dan Webb 11/2005
2
+ Version: 0.4
3
+
4
+ Usage:
5
+ Add a script tag for this script and any stylesets you need to use
6
+ to the page in question, add correct class names to CODE elements,
7
+ define CSS styles for elements. That's it!
8
+
9
+ Known to work on:
10
+ IE 5.5+ PC
11
+ Firefox/Mozilla PC/Mac
12
+ Opera 7.23 + PC
13
+ Safari 2
14
+
15
+ Known to degrade gracefully on:
16
+ IE5.0 PC
17
+
18
+ Note: IE5.0 fails due to the use of lookahead in some stylesets. To avoid script errors
19
+ in older browsers use expressions that use lookahead in string format when defining stylesets.
20
+
21
+ This script is inspired by star-light by entirely cunning Dean Edwards
22
+ http://dean.edwards.name/star-light/.
23
+ */
24
+
25
+ // replace callback support for safari.
26
+ if ("a".replace(/a/, function() {return "b"}) != "b") (function(){
27
+ var default_replace = String.prototype.replace;
28
+ String.prototype.replace = function(search,replace){
29
+ // replace is not function
30
+ if(typeof replace != "function"){
31
+ return default_replace.apply(this,arguments)
32
+ }
33
+ var str = "" + this;
34
+ var callback = replace;
35
+ // search string is not RegExp
36
+ if(!(search instanceof RegExp)){
37
+ var idx = str.indexOf(search);
38
+ return (
39
+ idx == -1 ? str :
40
+ default_replace.apply(str,[search,callback(search, idx, str)])
41
+ )
42
+ }
43
+ var reg = search;
44
+ var result = [];
45
+ var lastidx = reg.lastIndex;
46
+ var re;
47
+ while((re = reg.exec(str)) != null){
48
+ var idx = re.index;
49
+ var args = re.concat(idx, str);
50
+ result.push(
51
+ str.slice(lastidx,idx),
52
+ callback.apply(null,args).toString()
53
+ );
54
+ if(!reg.global){
55
+ lastidx += RegExp.lastMatch.length;
56
+ break
57
+ }else{
58
+ lastidx = reg.lastIndex;
59
+ }
60
+ }
61
+ result.push(str.slice(lastidx));
62
+ return result.join("")
63
+ }
64
+ })();
65
+
66
+ var CodeHighlighter = { styleSets : new Array };
67
+
68
+ CodeHighlighter.addStyle = function(name, rules) {
69
+ // using push test to disallow older browsers from adding styleSets
70
+ if ([].push) this.styleSets.push({
71
+ name : name,
72
+ rules : rules,
73
+ ignoreCase : arguments[2] || false
74
+ })
75
+
76
+ function setEvent() {
77
+ // set highlighter to run on load (use LowPro if present)
78
+ if (typeof Event != 'undefined' && typeof Event.onReady == 'function')
79
+ return Event.onReady(CodeHighlighter.init.bind(CodeHighlighter));
80
+
81
+ var old = window.onload;
82
+
83
+ if (typeof window.onload != 'function') {
84
+ window.onload = function() { CodeHighlighter.init() };
85
+ } else {
86
+ window.onload = function() {
87
+ old();
88
+ CodeHighlighter.init();
89
+ }
90
+ }
91
+ }
92
+
93
+ // only set the event when the first style is added
94
+ if (this.styleSets.length==1) setEvent();
95
+ }
96
+
97
+ CodeHighlighter.init = function() {
98
+ if (!document.getElementsByTagName) return;
99
+ if ("a".replace(/a/, function() {return "b"}) != "b") return; // throw out Safari versions that don't support replace function
100
+ // throw out older browsers
101
+
102
+ var codeEls = document.getElementsByTagName("CODE");
103
+ // collect array of all pre elements
104
+ codeEls.filter = function(f) {
105
+ var a = new Array;
106
+ for (var i = 0; i < this.length; i++) if (f(this[i])) a[a.length] = this[i];
107
+ return a;
108
+ }
109
+
110
+ var rules = new Array;
111
+ rules.toString = function() {
112
+ // joins regexes into one big parallel regex
113
+ var exps = new Array;
114
+ for (var i = 0; i < this.length; i++) exps.push(this[i].exp);
115
+ return exps.join("|");
116
+ }
117
+
118
+ function addRule(className, rule) {
119
+ // add a replace rule
120
+ var exp = (typeof rule.exp != "string")?String(rule.exp).substr(1, String(rule.exp).length-2):rule.exp;
121
+ // converts regex rules to strings and chops of the slashes
122
+ rules.push({
123
+ className : className,
124
+ exp : "(" + exp + ")",
125
+ length : (exp.match(/(^|[^\\])\([^?]/g) || "").length + 1, // number of subexps in rule
126
+ replacement : rule.replacement || null
127
+ });
128
+ }
129
+
130
+ function parse(text, ignoreCase) {
131
+ // main text parsing and replacement
132
+ return text.replace(new RegExp(rules, (ignoreCase)?"gi":"g"), function() {
133
+ var i = 0, j = 1, rule;
134
+ while (rule = rules[i++]) {
135
+ if (arguments[j]) {
136
+ // if no custom replacement defined do the simple replacement
137
+ if (!rule.replacement) return "<span class=\"" + rule.className + "\">" + arguments[0] + "</span>";
138
+ else {
139
+ // replace $0 with the className then do normal replaces
140
+ var str = rule.replacement.replace("$0", rule.className);
141
+ for (var k = 1; k <= rule.length - 1; k++) str = str.replace("$" + k, arguments[j + k]);
142
+ return str;
143
+ }
144
+ } else j+= rule.length;
145
+ }
146
+ });
147
+ }
148
+
149
+ function highlightCode(styleSet) {
150
+ // clear rules array
151
+ var parsed, clsRx = new RegExp("(\\s|^)" + styleSet.name + "(\\s|$)");
152
+ rules.length = 0;
153
+
154
+ // get stylable elements by filtering out all code elements without the correct className
155
+ var stylableEls = codeEls.filter(function(item) { return clsRx.test(item.className) });
156
+
157
+ // add style rules to parser
158
+ for (var className in styleSet.rules) addRule(className, styleSet.rules[className]);
159
+
160
+
161
+ // replace for all elements
162
+ for (var i = 0; i < stylableEls.length; i++) {
163
+ // EVIL hack to fix IE whitespace badness if it's inside a <pre>
164
+ if (/MSIE/.test(navigator.appVersion) && stylableEls[i].parentNode.nodeName == 'PRE') {
165
+ stylableEls[i] = stylableEls[i].parentNode;
166
+
167
+ parsed = stylableEls[i].innerHTML.replace(/(<code[^>]*>)([^<]*)<\/code>/i, function() {
168
+ return arguments[1] + parse(arguments[2], styleSet.ignoreCase) + "</code>"
169
+ });
170
+ parsed = parsed.replace(/\n( *)/g, function() {
171
+ var spaces = "";
172
+ for (var i = 0; i < arguments[1].length; i++) spaces+= "&nbsp;";
173
+ return "\n" + spaces;
174
+ });
175
+ parsed = parsed.replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;");
176
+ parsed = parsed.replace(/\n(<\/\w+>)?/g, "<br />$1").replace(/<br \/>[\n\r\s]*<br \/>/g, "<p><br></p>");
177
+
178
+ } else parsed = parse(stylableEls[i].innerHTML, styleSet.ignoreCase);
179
+
180
+ stylableEls[i].innerHTML = parsed;
181
+ }
182
+ }
183
+
184
+ // run highlighter on all stylesets
185
+ for (var i=0; i < this.styleSets.length; i++) {
186
+ highlightCode(this.styleSets[i]);
187
+ }
188
+ }
@@ -0,0 +1,18 @@
1
+ CodeHighlighter.addStyle("ruby",{
2
+ comment : {
3
+ exp : /#[^\n]+/
4
+ },
5
+ brackets : {
6
+ exp : /\(|\)/
7
+ },
8
+ string : {
9
+ exp : /'[^']*'|"[^"]*"/
10
+ },
11
+ keywords : {
12
+ exp : /\b(do|end|self|class|def|if|module|yield|then|else|for|until|unless|while|elsif|case|when|break|retry|redo|rescue|require|raise)\b/
13
+ },
14
+ /* Added by Shelly Fisher (shelly@agileevolved.com) */
15
+ symbol : {
16
+ exp : /([^:])(:[A-Za-z0-9_!?]+)/
17
+ }
18
+ });