saya 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.gitmodules +3 -0
- data/.travis.yml +11 -0
- data/CHANGES.md +5 -0
- data/Gemfile +4 -0
- data/LICENSE +201 -0
- data/README.md +75 -0
- data/Rakefile +24 -0
- data/bin/saya +5 -0
- data/config.ru +4 -0
- data/config/auth.yaml +14 -0
- data/config/rainbows.rb +4 -0
- data/config/zbatery.rb +4 -0
- data/lib/saya.rb +18 -0
- data/lib/saya/api.rb +144 -0
- data/lib/saya/init.rb +11 -0
- data/lib/saya/runner.rb +149 -0
- data/lib/saya/version.rb +4 -0
- data/public/index.html +146 -0
- data/public/jellyfish.png +0 -0
- data/saya.gemspec +66 -0
- data/task/.gitignore +1 -0
- data/task/gemgem.rb +268 -0
- metadata +141 -0
data/lib/saya/init.rb
ADDED
data/lib/saya/runner.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
|
2
|
+
require 'saya'
|
3
|
+
|
4
|
+
module Saya::Runner
|
5
|
+
module_function
|
6
|
+
def options
|
7
|
+
@options ||=
|
8
|
+
[['ruby options:' , '' ],
|
9
|
+
['-e, --eval LINE' ,
|
10
|
+
'Evaluate a LINE of code' ],
|
11
|
+
|
12
|
+
['-d, --debug' ,
|
13
|
+
'Set debugging flags (set $DEBUG to true)' ],
|
14
|
+
|
15
|
+
['-w, --warn' ,
|
16
|
+
'Turn warnings on (set $-w to true)' ],
|
17
|
+
|
18
|
+
['-I, --include PATH' ,
|
19
|
+
'Specify $LOAD_PATH (may be used more than once)' ],
|
20
|
+
|
21
|
+
['-r, --require LIBRARY' ,
|
22
|
+
'Require the library, before executing' ],
|
23
|
+
|
24
|
+
['saya options:' , '' ],
|
25
|
+
['-s, --server SERVER', 'Serve using SERVER' ],
|
26
|
+
['-o, --host HOST' , 'Listen on HOST (default: 0.0.0.0)' ],
|
27
|
+
['-p, --port PORT' , 'Use PORT (default: 8080)' ],
|
28
|
+
['-E, --env RACK_ENV' , 'Use RACK_ENV (default: production)' ],
|
29
|
+
['-D, --daemonize' , 'Run daemonized in the background' ],
|
30
|
+
['-a, --auth PATH' , 'Use AUTH file to specify key/secret' ],
|
31
|
+
['-y, --auth.yaml' , 'Print the content of default auth file' ],
|
32
|
+
['-c, --config.ru' , 'Print the path to config.ru' ],
|
33
|
+
['-h, --help' , 'Print this message' ],
|
34
|
+
['-v, --version' , 'Print the version' ]]
|
35
|
+
end
|
36
|
+
|
37
|
+
def run argv=ARGV
|
38
|
+
o = parse(argv)
|
39
|
+
u = %w[zbatery rainbows unicorn]
|
40
|
+
app, _ = Rack::Builder.parse_file(o[:config])
|
41
|
+
|
42
|
+
handler = if ( u.include?(o[:server]) && rack_handlers(o[:server])) ||
|
43
|
+
(!u.include?(o[:server]) && o[:server])
|
44
|
+
Rack::Handler.get(o[:server])
|
45
|
+
else
|
46
|
+
Rack::Handler.pick(u + %w[puma thin webrick])
|
47
|
+
end
|
48
|
+
|
49
|
+
Process.daemon && $0 = 'saya' if o[:daemonize]
|
50
|
+
handler.run(wrap_app(app), o)
|
51
|
+
end
|
52
|
+
|
53
|
+
def rack_handlers server
|
54
|
+
gem 'rack-handlers'
|
55
|
+
true
|
56
|
+
rescue Gem::LoadError
|
57
|
+
warn("Install gem `\e[31mrack-handlers\e[0m' to run #{server} server")
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
def wrap_app app
|
62
|
+
case ENV['RACK_ENV']
|
63
|
+
when 'development', 'dev'
|
64
|
+
Rack::CommonLogger.new(Rack::Lint.new(Rack::ShowExceptions.new(app)))
|
65
|
+
else
|
66
|
+
app
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def parse argv
|
71
|
+
options = {:Host => '0.0.0.0', :Port => 8080, :config => Saya::Config}
|
72
|
+
|
73
|
+
until argv.empty?
|
74
|
+
case arg = argv.shift
|
75
|
+
when /^-e=?(.+)?/, /^--eval=?(.+)?/
|
76
|
+
eval($1 || argv.shift, TOPLEVEL_BINDING, __FILE__, __LINE__)
|
77
|
+
|
78
|
+
when /^-d/, '--debug'
|
79
|
+
$DEBUG = true
|
80
|
+
argv.unshift("-#{arg[2..-1]}") if arg.size > 2
|
81
|
+
|
82
|
+
when /^-w/, '--warn'
|
83
|
+
$-w, $VERBOSE = true, true
|
84
|
+
argv.unshift("-#{arg[2..-1]}") if arg.size > 2
|
85
|
+
|
86
|
+
when /^-I=?(.+)?/, /^--include=?(.+)?/
|
87
|
+
paths = ($1 || argv.shift).split(':')
|
88
|
+
$LOAD_PATH.unshift(*paths)
|
89
|
+
|
90
|
+
when /^-r=?(.+)?/, /^--require=?(.+)?/
|
91
|
+
require($1 || argv.shift)
|
92
|
+
|
93
|
+
when /^-s=?(.+)?/, /^--server=?(.+)?/
|
94
|
+
options[:server] = $1 || argv.shift
|
95
|
+
|
96
|
+
when /^-o=?(.+)?/, /^--host=?(.+)?/
|
97
|
+
options[:Host] = $1 || argv.shift
|
98
|
+
|
99
|
+
when /^-p=?(.+)?/, /^--port=?(.+)?/
|
100
|
+
options[:Port] = $1 || argv.shift
|
101
|
+
|
102
|
+
when /^-E=?(.+)?/, /^--env=?(.+)?/
|
103
|
+
ENV['RACK_ENV'] = $1 || argv.shift
|
104
|
+
|
105
|
+
when /^-D/, '--daemonize'
|
106
|
+
options[:daemonize] = true
|
107
|
+
|
108
|
+
when /^-y/, '--auth.yaml' # reverse order to avoid mis-match
|
109
|
+
puts(File.read(Saya::Auth))
|
110
|
+
exit
|
111
|
+
|
112
|
+
when /^-a=?(.+)?/, /^--auth=?(.+)?/
|
113
|
+
ENV['SAYA_AUTH'] = $1 || argv.shift
|
114
|
+
|
115
|
+
when /^-c/, '--config.ru'
|
116
|
+
puts(options[:config])
|
117
|
+
exit
|
118
|
+
|
119
|
+
when /^-h/, '--help'
|
120
|
+
puts(help)
|
121
|
+
exit
|
122
|
+
|
123
|
+
when /^-v/, '--version'
|
124
|
+
require 'saya/version'
|
125
|
+
puts(Saya::VERSION)
|
126
|
+
exit
|
127
|
+
|
128
|
+
else
|
129
|
+
warn("Unrecognized option: #{arg}")
|
130
|
+
exit(1)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
options
|
135
|
+
end
|
136
|
+
|
137
|
+
def help
|
138
|
+
maxn = options.transpose.first.map(&:size).max
|
139
|
+
maxd = options.transpose.last .map(&:size).max
|
140
|
+
"Usage: saya [ruby OPTIONS] [saya OPTIONS]\n" +
|
141
|
+
options.map{ |(name, desc)|
|
142
|
+
if name.end_with?(':')
|
143
|
+
name
|
144
|
+
else
|
145
|
+
sprintf(" %-*s %-*s", maxn, name, maxd, desc)
|
146
|
+
end
|
147
|
+
}.join("\n")
|
148
|
+
end
|
149
|
+
end
|
data/lib/saya/version.rb
ADDED
data/public/index.html
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en" ng-app="saya">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title>Saya</title>
|
6
|
+
<link rel="icon" type="image/png" href="jellyfish.png">
|
7
|
+
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
|
8
|
+
|
9
|
+
<style type="text/css">
|
10
|
+
html, body{ height: 100%; }
|
11
|
+
#wrap{
|
12
|
+
min-height: 100%;
|
13
|
+
margin: 0 auto -60px;
|
14
|
+
}
|
15
|
+
#push, #footer{ height: 60px; }
|
16
|
+
#footer { background-color: #f5f5f5; }
|
17
|
+
#wrap > .container{ padding-top: 60px; }
|
18
|
+
.container .credit{ margin: 20px 0; }
|
19
|
+
.editarea, textarea{
|
20
|
+
width: 100%;
|
21
|
+
max-width: 767px;
|
22
|
+
height: 50vh;
|
23
|
+
}
|
24
|
+
@media(max-width: 979px){
|
25
|
+
#wrap > .container{ padding-top: 0; }
|
26
|
+
#footer{
|
27
|
+
margin-left: -20px;
|
28
|
+
margin-right: -20px;
|
29
|
+
padding-left: 20px;
|
30
|
+
padding-right: 20px;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
</style>
|
34
|
+
|
35
|
+
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
|
36
|
+
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular-cookies.min.js"></script>
|
37
|
+
<script>
|
38
|
+
angular.module('saya', ['ngCookies']);
|
39
|
+
function auth($scope, $http, $cookies){
|
40
|
+
['twitter', 'facebook'].forEach(function(target){
|
41
|
+
var checked = function(){
|
42
|
+
return $scope[target + "_name"]() !== undefined;
|
43
|
+
};
|
44
|
+
$scope[target + '_checked'] = checked;
|
45
|
+
$scope[target + '_as'] = function(){
|
46
|
+
if(checked()) return 'as';
|
47
|
+
};
|
48
|
+
$scope[target + '_name'] = function(){
|
49
|
+
return $cookies[target + '_name'];
|
50
|
+
};
|
51
|
+
|
52
|
+
$scope[target + '_auth'] = function(){
|
53
|
+
if(checked()){
|
54
|
+
$cookies[target + '_name'] = undefined;
|
55
|
+
}
|
56
|
+
else{
|
57
|
+
$http.post('/api/auth/' + target).success(
|
58
|
+
function(data){ window.location = data; });
|
59
|
+
}
|
60
|
+
};
|
61
|
+
});
|
62
|
+
};
|
63
|
+
</script>
|
64
|
+
|
65
|
+
</head>
|
66
|
+
<body>
|
67
|
+
<div id="wrap">
|
68
|
+
<div class="navbar navbar-inverse navbar-fixed-top">
|
69
|
+
<div class="navbar-inner">
|
70
|
+
<div class="container">
|
71
|
+
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
72
|
+
<span class="icon-bar"></span>
|
73
|
+
<span class="icon-bar"></span>
|
74
|
+
<span class="icon-bar"></span>
|
75
|
+
</button>
|
76
|
+
<div class="nav-collapse collapse">
|
77
|
+
<ul class="nav">
|
78
|
+
<li class="active"><a href="/">Saya</a></li>
|
79
|
+
<li><a href="#about" role="button" data-toggle="modal">About</a></li>
|
80
|
+
<li><a href="https://github.com/godfat/saya">Source</a></li>
|
81
|
+
</ul>
|
82
|
+
</div>
|
83
|
+
</div>
|
84
|
+
</div>
|
85
|
+
</div> <!-- navbar -->
|
86
|
+
|
87
|
+
<div class="container">
|
88
|
+
<div id="about" class="modal hide" tabindex="-1" role="dialog" aria-labelledby="aboutLabel" aria-hidden="true">
|
89
|
+
<div class="modal-header"><h3 id="aboutLabel">About Saya</h3></div>
|
90
|
+
<div class="modal-body">
|
91
|
+
<p>Saya helps you post a post to different SNS simultaneously.</p>
|
92
|
+
<p>It is intended to provide a reference usage for <a href="https://github.com/godfat/jellyfish">Jellyfish</a>.</p>
|
93
|
+
<p>
|
94
|
+
<table><tr>
|
95
|
+
<th>Runtime library:</th>
|
96
|
+
<th>Development library:</th></tr><tr><td><br/><ul>
|
97
|
+
<li><a href="http://angularjs.org/">AngularJS</a></li>
|
98
|
+
<li><a href="http://jquery.com/">jQuery</a> (for this About)</li>
|
99
|
+
<li><a href="http://twitter.github.io/bootstrap/">Bootstrap</a></li>
|
100
|
+
<li><a href="https://github.com/godfat/jellyfish">Jellyfish</a></li>
|
101
|
+
<li><a href="https://github.com/cardinalblue/rest-more">rest-more</a></li>
|
102
|
+
<li><a href="http://rack.github.io/">Rack</a></li>
|
103
|
+
<li><a href="https://github.com/godfat/rack-handlers">rack-handlers</a>(if Unicorn family is used)</li>
|
104
|
+
</ul></td><td><br/><ul>
|
105
|
+
<li><a href="https://github.com/chneukirchen/bacon">Bacon</a></li>
|
106
|
+
<li><a href="https://github.com/godfat/muack">Muack</a></li>
|
107
|
+
<li><a href="https://github.com/godfat/rib">Rib</a></li>
|
108
|
+
</ul></td></tr></table>
|
109
|
+
</p>
|
110
|
+
</div>
|
111
|
+
<div class="modal-footer">
|
112
|
+
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
|
113
|
+
</div>
|
114
|
+
</div> <!-- about -->
|
115
|
+
|
116
|
+
<div class="main">
|
117
|
+
<p>Say something to the following sites:</p>
|
118
|
+
<form action="/api/post" method="post" ng-controller="auth">
|
119
|
+
<label class="checkbox">
|
120
|
+
<input type="checkbox" name="twitter" ng-click="twitter_auth()" ng-checked="twitter_checked()"/>
|
121
|
+
Twitter {{twitter_as()}} <span class="label label-success">{{twitter_name()}}</span>
|
122
|
+
</label>
|
123
|
+
<label class="checkbox">
|
124
|
+
<input type="checkbox" name="facebook" ng-click="facebook_auth()" ng-checked="facebook_checked()"/>
|
125
|
+
Facebook {{facebook_as()}} <span class="label label-success">{{facebook_name()}}</span>
|
126
|
+
</label>
|
127
|
+
<div class="editarea">
|
128
|
+
<p><textarea id="textarea" name="post"></textarea></p>
|
129
|
+
<p class="pagination-centered"><button type="submit" class="btn">Say!</button></p>
|
130
|
+
</div>
|
131
|
+
</form>
|
132
|
+
</div> <!-- main -->
|
133
|
+
</div> <!-- container -->
|
134
|
+
|
135
|
+
<div id="push"></div>
|
136
|
+
</div> <!-- wrap -->
|
137
|
+
|
138
|
+
<div id="footer">
|
139
|
+
<div class="container">
|
140
|
+
<p class="muted credit">Powered by <a href="https://github.com/godfat/jellyfish">Jellyfish</a> and <a href="https://github.com/cardinalblue/rest-more">rest-more</a>.</p>
|
141
|
+
</div>
|
142
|
+
</div> <!-- footer -->
|
143
|
+
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
144
|
+
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
|
145
|
+
</body>
|
146
|
+
</html>
|
Binary file
|
data/saya.gemspec
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "saya"
|
5
|
+
s.version = "0.0.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Lin Jen-Shin (godfat)"]
|
9
|
+
s.date = "2013-07-12"
|
10
|
+
s.description = "Saya helps you post a post to different SNS simultaneously.\n\nIt is intended to provide a reference usage for [Jellyfish](https://github.com/godfat/jellyfish)."
|
11
|
+
s.email = ["godfat (XD) godfat.org"]
|
12
|
+
s.executables = ["saya"]
|
13
|
+
s.files = [
|
14
|
+
".gitignore",
|
15
|
+
".gitmodules",
|
16
|
+
".travis.yml",
|
17
|
+
"CHANGES.md",
|
18
|
+
"Gemfile",
|
19
|
+
"LICENSE",
|
20
|
+
"README.md",
|
21
|
+
"Rakefile",
|
22
|
+
"bin/saya",
|
23
|
+
"config.ru",
|
24
|
+
"config/auth.yaml",
|
25
|
+
"config/rainbows.rb",
|
26
|
+
"config/zbatery.rb",
|
27
|
+
"lib/saya.rb",
|
28
|
+
"lib/saya/api.rb",
|
29
|
+
"lib/saya/init.rb",
|
30
|
+
"lib/saya/runner.rb",
|
31
|
+
"lib/saya/version.rb",
|
32
|
+
"public/index.html",
|
33
|
+
"public/jellyfish.png",
|
34
|
+
"saya.gemspec",
|
35
|
+
"task/.gitignore",
|
36
|
+
"task/gemgem.rb"]
|
37
|
+
s.homepage = "https://github.com/godfat/saya"
|
38
|
+
s.licenses = ["Apache License 2.0"]
|
39
|
+
s.require_paths = ["lib"]
|
40
|
+
s.rubygems_version = "2.0.5"
|
41
|
+
s.summary = "Saya helps you post a post to different SNS simultaneously."
|
42
|
+
|
43
|
+
if s.respond_to? :specification_version then
|
44
|
+
s.specification_version = 4
|
45
|
+
|
46
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
47
|
+
s.add_runtime_dependency(%q<rack>, [">= 0"])
|
48
|
+
s.add_runtime_dependency(%q<jellyfish>, [">= 0"])
|
49
|
+
s.add_runtime_dependency(%q<rest-more>, [">= 0"])
|
50
|
+
s.add_development_dependency(%q<bacon>, [">= 0"])
|
51
|
+
s.add_development_dependency(%q<rack-handlers>, [">= 0"])
|
52
|
+
else
|
53
|
+
s.add_dependency(%q<rack>, [">= 0"])
|
54
|
+
s.add_dependency(%q<jellyfish>, [">= 0"])
|
55
|
+
s.add_dependency(%q<rest-more>, [">= 0"])
|
56
|
+
s.add_dependency(%q<bacon>, [">= 0"])
|
57
|
+
s.add_dependency(%q<rack-handlers>, [">= 0"])
|
58
|
+
end
|
59
|
+
else
|
60
|
+
s.add_dependency(%q<rack>, [">= 0"])
|
61
|
+
s.add_dependency(%q<jellyfish>, [">= 0"])
|
62
|
+
s.add_dependency(%q<rest-more>, [">= 0"])
|
63
|
+
s.add_dependency(%q<bacon>, [">= 0"])
|
64
|
+
s.add_dependency(%q<rack-handlers>, [">= 0"])
|
65
|
+
end
|
66
|
+
end
|
data/task/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.rbc
|
data/task/gemgem.rb
ADDED
@@ -0,0 +1,268 @@
|
|
1
|
+
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
module Gemgem
|
5
|
+
class << self
|
6
|
+
attr_accessor :dir, :spec
|
7
|
+
end
|
8
|
+
|
9
|
+
module_function
|
10
|
+
def create
|
11
|
+
yield(spec = Gem::Specification.new{ |s|
|
12
|
+
s.authors = ['Lin Jen-Shin (godfat)']
|
13
|
+
s.email = ['godfat (XD) godfat.org']
|
14
|
+
|
15
|
+
s.description = description.join
|
16
|
+
s.summary = description.first
|
17
|
+
s.license = readme['LICENSE'].sub(/.+\n\n/, '').lines.first.strip
|
18
|
+
|
19
|
+
s.rubygems_version = Gem::VERSION
|
20
|
+
s.date = Time.now.strftime('%Y-%m-%d')
|
21
|
+
s.files = gem_files
|
22
|
+
s.test_files = gem_files.grep(%r{^test/(.+?/)*test_.+?\.rb$})
|
23
|
+
s.executables = Dir['bin/*'].map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = %w[lib]
|
25
|
+
})
|
26
|
+
spec.homepage ||= "https://github.com/godfat/#{spec.name}"
|
27
|
+
spec
|
28
|
+
end
|
29
|
+
|
30
|
+
def readme
|
31
|
+
path = %w[README.md README].find{ |name|
|
32
|
+
File.exist?("#{Gemgem.dir}/#{name}")
|
33
|
+
}
|
34
|
+
@readme ||=
|
35
|
+
if path
|
36
|
+
ps = "##{File.read(path)}".
|
37
|
+
scan(/((#+)[^\n]+\n\n.+?(?=(\n\n\2[^#\n]+\n)|\Z))/m).map(&:first)
|
38
|
+
ps.inject('HEADER' => ps.first){ |r, s, i|
|
39
|
+
r[s[/\w+/]] = s
|
40
|
+
r
|
41
|
+
}
|
42
|
+
else
|
43
|
+
{}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def description
|
48
|
+
@description ||= (readme['DESCRIPTION']||'').sub(/.+\n\n/, '').lines
|
49
|
+
end
|
50
|
+
|
51
|
+
def changes
|
52
|
+
path = %w[CHANGES.md CHANGES].find{ |name|
|
53
|
+
File.exist?("#{Gemgem.dir}/#{name}")
|
54
|
+
}
|
55
|
+
@changes ||=
|
56
|
+
if path
|
57
|
+
date = '\d+{4}\-\d+{2}\-\d{2}'
|
58
|
+
File.read(path).match(
|
59
|
+
/([^\n]+#{date}\n\n(.+?))(?=\n\n[^\n]+#{date}\n|\Z)/m)[1]
|
60
|
+
else
|
61
|
+
''
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def ann_md
|
66
|
+
"#{readme['HEADER'].sub(/([\w\-]+)/, "[\\1](#{spec.homepage})")}\n\n" \
|
67
|
+
"##{readme['DESCRIPTION'][/[^\n]+\n\n[^\n]+/]}\n\n" \
|
68
|
+
"### CHANGES:\n\n" \
|
69
|
+
"###{changes}\n\n" \
|
70
|
+
"##{readme['INSTALLATION']}\n\n" +
|
71
|
+
if readme['SYNOPSIS'] then "##{readme['SYNOPSIS'][/[^\n]+\n\n[^\n]+/]}"
|
72
|
+
else '' end
|
73
|
+
end
|
74
|
+
|
75
|
+
def ann_html
|
76
|
+
gem 'nokogiri'
|
77
|
+
gem 'kramdown'
|
78
|
+
|
79
|
+
IO.popen('kramdown', 'r+') do |md|
|
80
|
+
md.puts Gemgem.ann_md
|
81
|
+
md.close_write
|
82
|
+
require 'nokogiri'
|
83
|
+
html = Nokogiri::XML.parse("<gemgem>#{md.read}</gemgem>")
|
84
|
+
html.css('*').each{ |n| n.delete('id') }
|
85
|
+
html.root.children.to_html
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def ann_email
|
90
|
+
"#{readme['HEADER'].sub(/([\w\-]+)/, "\\1 <#{spec.homepage}>")}\n\n" \
|
91
|
+
"#{readme['DESCRIPTION']}\n\n" \
|
92
|
+
"#{readme['INSTALLATION']}\n\n" +
|
93
|
+
if readme['SYNOPSIS'] then "##{readme['SYNOPSIS']}\n\n" else '' end +
|
94
|
+
"## CHANGES:\n\n" \
|
95
|
+
"##{changes}\n\n"
|
96
|
+
end
|
97
|
+
|
98
|
+
def gem_tag
|
99
|
+
"#{spec.name}-#{spec.version}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def write
|
103
|
+
File.open("#{dir}/#{spec.name}.gemspec", 'w'){ |f|
|
104
|
+
f << split_lines(spec.to_ruby) }
|
105
|
+
end
|
106
|
+
|
107
|
+
def split_lines ruby
|
108
|
+
ruby.gsub(/(.+?)\s*=\s*\[(.+?)\]/){ |s|
|
109
|
+
if $2.index(',')
|
110
|
+
"#{$1} = [\n #{$2.split(',').map(&:strip).join(",\n ")}]"
|
111
|
+
else
|
112
|
+
s
|
113
|
+
end
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
def all_files
|
118
|
+
@all_files ||= find_files(Pathname.new(dir)).map{ |file|
|
119
|
+
if file.to_s =~ %r{\.git/|\.git$}
|
120
|
+
nil
|
121
|
+
else
|
122
|
+
file.to_s
|
123
|
+
end
|
124
|
+
}.compact.sort
|
125
|
+
end
|
126
|
+
|
127
|
+
def gem_files
|
128
|
+
@gem_files ||= all_files - ignored_files
|
129
|
+
end
|
130
|
+
|
131
|
+
def ignored_files
|
132
|
+
@ignored_file ||= all_files.select{ |path| ignore_patterns.find{ |ignore|
|
133
|
+
path =~ ignore && !git_files.include?(path)}}
|
134
|
+
end
|
135
|
+
|
136
|
+
def git_files
|
137
|
+
@git_files ||= if File.exist?("#{dir}/.git")
|
138
|
+
`git ls-files`.split("\n")
|
139
|
+
else
|
140
|
+
[]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# protected
|
145
|
+
def find_files path
|
146
|
+
path.children.select(&:file?).map{|file| file.to_s[(dir.size+1)..-1]} +
|
147
|
+
path.children.select(&:directory?).map{|dir| find_files(dir)}.flatten
|
148
|
+
end
|
149
|
+
|
150
|
+
def ignore_patterns
|
151
|
+
@ignore_files ||= expand_patterns(
|
152
|
+
gitignore.split("\n").reject{ |pattern|
|
153
|
+
pattern.strip == ''
|
154
|
+
}).map{ |pattern| %r{^([^/]+/)*?#{Regexp.escape(pattern)}(/[^/]+)*?$} }
|
155
|
+
end
|
156
|
+
|
157
|
+
def expand_patterns pathes
|
158
|
+
pathes.map{ |path|
|
159
|
+
if path !~ /\*/
|
160
|
+
path
|
161
|
+
else
|
162
|
+
expand_patterns(
|
163
|
+
Dir[path] +
|
164
|
+
Pathname.new(File.dirname(path)).children.select(&:directory?).
|
165
|
+
map{ |prefix| "#{prefix}/#{File.basename(path)}" })
|
166
|
+
end
|
167
|
+
}.flatten
|
168
|
+
end
|
169
|
+
|
170
|
+
def gitignore
|
171
|
+
if File.exist?(path = "#{dir}/.gitignore")
|
172
|
+
File.read(path)
|
173
|
+
else
|
174
|
+
''
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
namespace :gem do
|
180
|
+
|
181
|
+
desc 'Install gem'
|
182
|
+
task :install => [:build] do
|
183
|
+
sh("#{Gem.ruby} -S gem install pkg/#{Gemgem.gem_tag}.gem")
|
184
|
+
end
|
185
|
+
|
186
|
+
desc 'Build gem'
|
187
|
+
task :build => [:spec] do
|
188
|
+
sh("#{Gem.ruby} -S gem build #{Gemgem.spec.name}.gemspec")
|
189
|
+
sh("mkdir -p pkg")
|
190
|
+
sh("mv #{Gemgem.gem_tag}.gem pkg/")
|
191
|
+
end
|
192
|
+
|
193
|
+
desc 'Release gem'
|
194
|
+
task :release => [:spec, :check, :build] do
|
195
|
+
sh("git tag #{Gemgem.gem_tag}")
|
196
|
+
sh("git push")
|
197
|
+
sh("git push --tags")
|
198
|
+
sh("#{Gem.ruby} -S gem push pkg/#{Gemgem.gem_tag}.gem")
|
199
|
+
end
|
200
|
+
|
201
|
+
task :check do
|
202
|
+
ver = Gemgem.spec.version.to_s
|
203
|
+
|
204
|
+
if ENV['VERSION'].nil?
|
205
|
+
puts("\e[35mExpected " \
|
206
|
+
"\e[33mVERSION\e[35m=\e[33m#{ver}\e[0m")
|
207
|
+
exit(1)
|
208
|
+
|
209
|
+
elsif ENV['VERSION'] != ver
|
210
|
+
puts("\e[35mExpected \e[33mVERSION\e[35m=\e[33m#{ver} " \
|
211
|
+
"\e[35mbut got\n " \
|
212
|
+
"\e[33mVERSION\e[35m=\e[33m#{ENV['VERSION']}\e[0m")
|
213
|
+
exit(2)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
end # of gem namespace
|
218
|
+
|
219
|
+
desc 'Run tests in memory'
|
220
|
+
task :test do
|
221
|
+
require 'bacon'
|
222
|
+
Bacon.extend(Bacon::TestUnitOutput)
|
223
|
+
Bacon.summary_on_exit
|
224
|
+
$LOAD_PATH.unshift('lib')
|
225
|
+
Dir['./test/**/test_*.rb'].each{ |file| require file[0..-4] }
|
226
|
+
end
|
227
|
+
|
228
|
+
desc 'Run tests with shell'
|
229
|
+
task 'test:shell', :RUBY_OPTS do |t, args|
|
230
|
+
files = Dir['test/**/test_*.rb'].join(' ')
|
231
|
+
|
232
|
+
cmd = [Gem.ruby, args[:RUBY_OPTS],
|
233
|
+
'-I', 'lib', '-S', 'bacon', '--quiet', files]
|
234
|
+
|
235
|
+
sh(cmd.compact.join(' '))
|
236
|
+
end
|
237
|
+
|
238
|
+
desc 'Generate ann markdown'
|
239
|
+
task 'ann:md' => ['gem:spec'] do
|
240
|
+
puts Gemgem.ann_md
|
241
|
+
end
|
242
|
+
|
243
|
+
desc 'Generate ann html'
|
244
|
+
task 'ann:html' => ['gem:spec'] do
|
245
|
+
puts Gemgem.ann_html
|
246
|
+
end
|
247
|
+
|
248
|
+
desc 'Generate ann email'
|
249
|
+
task 'ann:email' => ['gem:spec'] do
|
250
|
+
puts Gemgem.ann_email
|
251
|
+
end
|
252
|
+
|
253
|
+
desc 'Generate rdoc'
|
254
|
+
task :doc => ['gem:spec'] do
|
255
|
+
sh("yardoc -o rdoc --main README.md" \
|
256
|
+
" --files #{Gemgem.spec.extra_rdoc_files.join(',')}")
|
257
|
+
end
|
258
|
+
|
259
|
+
desc 'Remove ignored files'
|
260
|
+
task :clean => ['gem:spec'] do
|
261
|
+
trash = "~/.Trash/#{Gemgem.spec.name}/"
|
262
|
+
sh "mkdir -p #{trash}" unless File.exist?(File.expand_path(trash))
|
263
|
+
Gemgem.ignored_files.each{ |file| sh "mv #{file} #{trash}" }
|
264
|
+
end
|
265
|
+
|
266
|
+
task :default do
|
267
|
+
puts `#{Gem.ruby} -S #{$PROGRAM_NAME} -T`
|
268
|
+
end
|