capitate 0.2.11 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +9 -0
- data/Manifest.txt +11 -1
- data/lib/capitate/cap_ext/connections.rb +15 -8
- data/lib/capitate/cap_ext/run_via.rb +2 -0
- data/lib/capitate/cap_ext/variables.rb +9 -2
- data/lib/capitate/plugins/base.rb +17 -12
- data/lib/capitate/plugins/build.rb +14 -11
- data/lib/capitate/plugins/prompt.rb +6 -8
- data/lib/capitate/plugins/script.rb +6 -4
- data/lib/capitate/plugins/templates.rb +16 -7
- data/lib/capitate/plugins/upload.rb +2 -1
- data/lib/capitate/plugins/utils.rb +7 -5
- data/lib/capitate/task_node.rb +30 -32
- data/lib/capitate/version.rb +1 -1
- data/lib/recipes/backgroundrb.rb +18 -4
- data/lib/recipes/centos/backgroundrb.rb +10 -3
- data/lib/recipes/centos/centos.rb +21 -8
- data/lib/recipes/centos/imagemagick.rb +4 -1
- data/lib/recipes/centos/memcached.rb +26 -8
- data/lib/recipes/centos/mongrel_cluster.rb +33 -13
- data/lib/recipes/centos/monit.rb +32 -11
- data/lib/recipes/centos/mysql.rb +7 -2
- data/lib/recipes/centos/nginx.rb +29 -10
- data/lib/recipes/centos/ruby.rb +11 -2
- data/lib/recipes/centos/sphinx.rb +32 -10
- data/lib/recipes/docs.rb +12 -7
- data/lib/recipes/logrotate/backgroundrb.rb +25 -0
- data/lib/recipes/logrotated.rb +18 -12
- data/lib/recipes/memcached.rb +0 -25
- data/lib/recipes/monit/backgroundrb.rb +39 -0
- data/lib/recipes/monit/memcached.rb +22 -0
- data/lib/recipes/{mongrel_cluster.rb → monit/mongrel_cluster.rb} +22 -12
- data/lib/recipes/monit/mysql.rb +21 -0
- data/lib/recipes/monit/nginx.rb +34 -0
- data/lib/recipes/monit/sphinx.rb +29 -0
- data/lib/recipes/monit/sshd.rb +27 -0
- data/lib/recipes/monit.rb +18 -3
- data/lib/recipes/mysql.rb +22 -32
- data/lib/recipes/nginx.rb +15 -30
- data/lib/recipes/rails.rb +17 -6
- data/lib/recipes/sphinx.rb +11 -24
- data/lib/recipes/sshd.rb +4 -22
- data/lib/recipes/syslogd.rb +4 -0
- data/lib/templates/backgroundrb/backgroundrb.monitrc.erb +4 -0
- data/lib/templates/backgroundrb/backgroundrb.yml.erb +4 -0
- data/website/index.html +10 -2
- data/website/javascripts/code_highlighter.js +188 -0
- data/website/javascripts/ruby.js +18 -0
- data/website/stylesheets/screen.css +116 -23
- data/website/template.rhtml +9 -1
- data/website/template_recipe.rhtml +12 -1
- 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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
4
|
+
desc <<-DESC
|
5
|
+
Create database, database user, and set grant permissions.
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
<dl>
|
8
|
+
<dt>db_name</dt>
|
9
|
+
<dd>Database name (application).</dd>
|
8
10
|
|
9
|
-
|
10
|
-
|
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
|
-
|
29
|
-
|
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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
53
|
-
|
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
|
66
|
-
|
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
|
91
|
-
|
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 = ''
|
data/lib/recipes/sphinx.rb
CHANGED
@@ -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
|
|
data/lib/recipes/syslogd.rb
CHANGED
@@ -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
|
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.
|
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
|
-
|
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+= " ";
|
173
|
+
return "\n" + spaces;
|
174
|
+
});
|
175
|
+
parsed = parsed.replace(/\t/g, " ");
|
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
|
+
});
|