capitate 0.2.11 → 0.2.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
});
|