tay 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +135 -0
- data/Rakefile +6 -0
- data/bin/tay +15 -0
- data/lib/tay.rb +19 -0
- data/lib/tay/builder.rb +173 -0
- data/lib/tay/cli.rb +29 -0
- data/lib/tay/cli/build.rb +15 -0
- data/lib/tay/cli/generate.rb +73 -0
- data/lib/tay/cli/generators/browser_action.rb +20 -0
- data/lib/tay/cli/generators/content_script.rb +37 -0
- data/lib/tay/cli/generators/page_action.rb +19 -0
- data/lib/tay/cli/generators/templates/browser_action/action.css +4 -0
- data/lib/tay/cli/generators/templates/browser_action/action.html +11 -0
- data/lib/tay/cli/generators/templates/browser_action/action.js +5 -0
- data/lib/tay/cli/generators/templates/browser_action/tayfile +7 -0
- data/lib/tay/cli/generators/templates/content_script/content_script.css +6 -0
- data/lib/tay/cli/generators/templates/content_script/content_script.js +4 -0
- data/lib/tay/cli/generators/templates/content_script/tayfile +6 -0
- data/lib/tay/cli/generators/templates/page_action/controller.js +7 -0
- data/lib/tay/cli/generators/templates/page_action/icon.png +0 -0
- data/lib/tay/cli/generators/templates/page_action/tayfile +7 -0
- data/lib/tay/cli/helpers.rb +51 -0
- data/lib/tay/cli/minify.rb +44 -0
- data/lib/tay/cli/new.rb +37 -0
- data/lib/tay/cli/package.rb +41 -0
- data/lib/tay/cli/templates/Gemfile +30 -0
- data/lib/tay/cli/templates/Tayfile +22 -0
- data/lib/tay/cli/templates/gitignore +5 -0
- data/lib/tay/cli/validate.rb +21 -0
- data/lib/tay/cli/watch.rb +29 -0
- data/lib/tay/manifest_generator.rb +160 -0
- data/lib/tay/packager.rb +64 -0
- data/lib/tay/specification.rb +261 -0
- data/lib/tay/specification/action.rb +18 -0
- data/lib/tay/specification/browser_action.rb +10 -0
- data/lib/tay/specification/content_script.rb +41 -0
- data/lib/tay/specification/nacl_module.rb +18 -0
- data/lib/tay/specification/packaged_app.rb +33 -0
- data/lib/tay/specification/page_action.rb +10 -0
- data/lib/tay/specification/web_intent.rb +40 -0
- data/lib/tay/specification_validator.rb +167 -0
- data/lib/tay/utils.rb +21 -0
- data/lib/tay/version.rb +3 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/tay_spec.rb +5 -0
- data/tay.gemspec +26 -0
- metadata +215 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
module Tay
|
2
|
+
module CLI
|
3
|
+
class Generate < ::Thor
|
4
|
+
include ::Thor::Actions
|
5
|
+
include Tay::CLI::Helpers
|
6
|
+
|
7
|
+
class_option 'tayfile', :type => :string,
|
8
|
+
:banner => 'Use the specified tayfile instead of Tayfile'
|
9
|
+
class_option 'build-directory', :type => :string, :default => 'build',
|
10
|
+
:aliases => '-b', :banner => 'The directory containing the built extension'
|
11
|
+
|
12
|
+
def self.source_root
|
13
|
+
File.expand_path('generators/templates', File.dirname(__FILE__))
|
14
|
+
end
|
15
|
+
|
16
|
+
require 'tay/cli/generators/page_action'
|
17
|
+
require 'tay/cli/generators/browser_action'
|
18
|
+
require 'tay/cli/generators/content_script'
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
##
|
23
|
+
# Take some content and inject it inside the Tay::Specification
|
24
|
+
def inject_tayfile_content(new_content)
|
25
|
+
tayfile_contents = tayfile_path.read.strip
|
26
|
+
tayfile_contents.sub!(/end\Z/, "\n" + new_content + "\nend")
|
27
|
+
tayfile_path.open('w') do |f|
|
28
|
+
f.write(tayfile_contents)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Render a template in the context of self and return its contents
|
34
|
+
# Thor does not provide a way to do this.
|
35
|
+
def render_template(path, locals = {})
|
36
|
+
tayfile_template = Tilt::ERBTemplate.new(find_in_source_paths(path), {
|
37
|
+
:trim => '-'
|
38
|
+
})
|
39
|
+
tayfile_template.render(self, locals)
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Get path to src/assets
|
44
|
+
def asset_dir
|
45
|
+
src_dir.join('assets')
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Get path to src/html
|
50
|
+
def html_dir
|
51
|
+
src_dir.join('html')
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Get path to src/stylesheets
|
56
|
+
def stylesheet_dir
|
57
|
+
src_dir.join('stylesheets')
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Get path to src/javascripts
|
62
|
+
def javascript_dir
|
63
|
+
src_dir.join('javascripts')
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Get path to the src directory
|
68
|
+
def src_dir
|
69
|
+
tayfile_path.dirname.join('src')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Tay
|
2
|
+
module CLI
|
3
|
+
class Generate < ::Thor
|
4
|
+
desc "browser_action", "Generate a browser action"
|
5
|
+
method_option 'action-name', :type => :string, :default => 'Browser Action',
|
6
|
+
:aliases => '-n', :banner => 'The name of the browser action'
|
7
|
+
def browser_action
|
8
|
+
raise Tay::InvalidSpecification.new("Browser action already specified") if spec.browser_action
|
9
|
+
raise Tay::InvalidSpecification.new("You cannot have both browser and page actions") if spec.browser_action
|
10
|
+
raise Tay::InvalidSpecification.new("You cannot have both browser actions and packaged apps") if spec.packaged_app
|
11
|
+
|
12
|
+
fs_name = Utils.filesystem_name(options['action-name'])
|
13
|
+
copy_file('browser_action/action.js', javascript_dir.join(fs_name+ '.js'))
|
14
|
+
copy_file('browser_action/action.css', stylesheet_dir.join(fs_name+ '.css'))
|
15
|
+
create_file(html_dir.join(fs_name+ '.html'), render_template('browser_action/action.html', :fs_name => fs_name))
|
16
|
+
inject_tayfile_content(render_template('browser_action/tayfile', :fs_name => fs_name))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Tay
|
2
|
+
module CLI
|
3
|
+
class Generate < ::Thor
|
4
|
+
desc "content_script", "Generate a content script"
|
5
|
+
def content_script
|
6
|
+
copy_file('content_script/content_script.js', javascript_dir.join('content_script.js'))
|
7
|
+
copy_file('content_script/content_script.css', stylesheet_dir.join('content_script.css'))
|
8
|
+
inject_tayfile_content(File.read(find_in_source_paths('content_script/tayfile_content')))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Tay
|
15
|
+
module CLI
|
16
|
+
class Generate < ::Thor
|
17
|
+
desc "content_script", "Generate a content script"
|
18
|
+
method_option 'script-name', :type => :string, :default => 'content_script',
|
19
|
+
:aliases => '-n', :banner => 'The name of the content script'
|
20
|
+
method_option 'no-javascript', :type => :boolean, :default => false,
|
21
|
+
:banner => "Don\'t create a javascript file"
|
22
|
+
method_option 'no-stylesheet', :type => :boolean, :default => false,
|
23
|
+
:banner => "Don\'t create a stylesheet"
|
24
|
+
def content_script
|
25
|
+
fs_name = Utils.filesystem_name(options['script-name'])
|
26
|
+
|
27
|
+
unless options['no-javascript']
|
28
|
+
copy_file('content_script/content_script.js', javascript_dir.join(fs_name + '.js'))
|
29
|
+
end
|
30
|
+
unless options['no-stylesheet']
|
31
|
+
copy_file('content_script/content_script.css', stylesheet_dir.join(fs_name + '.css'))
|
32
|
+
end
|
33
|
+
inject_tayfile_content(render_template('content_script/tayfile', :fs_name => fs_name))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Tay
|
2
|
+
module CLI
|
3
|
+
class Generate < ::Thor
|
4
|
+
desc "page_action", "Generate a page action"
|
5
|
+
method_option 'action-name', :type => :string, :default => 'Page Action',
|
6
|
+
:aliases => '-n', :banner => 'The name of the page action'
|
7
|
+
def page_action
|
8
|
+
raise Tay::InvalidSpecification.new("Page action already specified") if spec.page_action
|
9
|
+
raise Tay::InvalidSpecification.new("You cannot have both page and browser actions") if spec.browser_action
|
10
|
+
raise Tay::InvalidSpecification.new("You cannot have both page actions and packaged apps") if spec.packaged_app
|
11
|
+
|
12
|
+
fs_name = Utils.filesystem_name(options['action-name'])
|
13
|
+
copy_file('page_action/icon.png', asset_dir.join(fs_name + '_icon.png'))
|
14
|
+
copy_file('page_action/controller.js', javascript_dir.join(fs_name + '_controller.js'))
|
15
|
+
inject_tayfile_content(render_template('page_action/tayfile', :fs_name => fs_name))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title><%= options['action-name'] %></title>
|
5
|
+
<script src="/javascripts/<%= fs_name %>.js"></script>
|
6
|
+
<link rel="stylesheet" type="text/css" href="/stylesheets/<%= fs_name %>.css">
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<h1>Hello World!</h1>
|
10
|
+
</body>
|
11
|
+
</html>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
ext.stylesheets << 'stylesheets/<%= fs_name %>.css'
|
2
|
+
ext.javascripts << 'javascripts/<%= fs_name %>.js'
|
3
|
+
ext.add_browser_action do |ba|
|
4
|
+
ba.title = '<%= options['action-name'] %>'
|
5
|
+
ba.popup = 'html/<%= fs_name %>.html'
|
6
|
+
# ba.icon = 'assets/<%= fs_name %>_icon.png'
|
7
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
# Go to http://www.iana.org/domains/example/ to see the effects
|
2
|
+
ext.add_content_script do |cs|
|
3
|
+
cs.include_patterns << 'http://www.iana.org/domains/*'
|
4
|
+
<%= " cs.stylesheets << 'stylesheets/#{fs_name}.css'\n" unless options['no-stylesheet'] -%>
|
5
|
+
<%= " cs.javascripts << 'javascripts/#{fs_name}.js'\n" unless options['no-javascript'] -%>
|
6
|
+
end
|
Binary file
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<%= " ext.permissions << 'tabs'\n" unless spec.has_permission?('tabs') -%>
|
2
|
+
ext.background_scripts << 'javascripts/<%= fs_name %>_controller.js'
|
3
|
+
ext.add_page_action do |pa|
|
4
|
+
pa.title = '<%= options['action-name'] %>'
|
5
|
+
pa.icon = 'assets/<%= fs_name %>_icon.png'
|
6
|
+
# pa.popup = 'html/<%= fs_name %>_popup.html'
|
7
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Tay
|
2
|
+
module CLI
|
3
|
+
module Helpers
|
4
|
+
DEFAULT_TAYFILE = 'Tayfile'
|
5
|
+
|
6
|
+
protected
|
7
|
+
|
8
|
+
def spec
|
9
|
+
@spec ||= get_specification
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_specification(path = nil)
|
13
|
+
path = path ? Pathname.new(path) : tayfile_path
|
14
|
+
|
15
|
+
unless path.exist?
|
16
|
+
if options['tayfile'].nil?
|
17
|
+
message = "No Tayfile was found in the current directory"
|
18
|
+
else
|
19
|
+
message = "#{path} does not exist"
|
20
|
+
end
|
21
|
+
raise SpecificationNotFound.new(message)
|
22
|
+
end
|
23
|
+
|
24
|
+
eval(File.open(path).read)
|
25
|
+
end
|
26
|
+
|
27
|
+
def tayfile_path
|
28
|
+
Pathname.new(options['tayfile'] || DEFAULT_TAYFILE).expand_path
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Return the base directory for this extension
|
33
|
+
def base_dir
|
34
|
+
tayfile_path.dirname
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Return the src directory for this extension
|
39
|
+
def src_dir
|
40
|
+
base_dir.join('src')
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Return the build directory for this extension, respecting any command
|
45
|
+
# line option
|
46
|
+
def build_dir
|
47
|
+
base_dir.join(options['build-directory'] || 'build')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Tay
|
2
|
+
module CLI
|
3
|
+
class Root < ::Thor
|
4
|
+
desc 'minify', 'Minify the CSS and JS of the currently built extension'
|
5
|
+
method_option 'tayfile', :type => :string,
|
6
|
+
:banner => 'Use the specified tayfile instead of Tayfile'
|
7
|
+
method_option 'build-directory', :type => :string, :default => 'build',
|
8
|
+
:aliases => '-b', :banner => 'The directory containing the built extension'
|
9
|
+
method_option 'skip-js', :type => :boolean, :default => false,
|
10
|
+
:banner => "Don't minify *.js files"
|
11
|
+
method_option 'skip-css', :type => :boolean, :default => false,
|
12
|
+
:banner => "Don't minify *.css files"
|
13
|
+
def minify
|
14
|
+
unless options['skip-js']
|
15
|
+
begin
|
16
|
+
require 'uglifier'
|
17
|
+
Dir[build_dir.join('**/*.js')].each do |path|
|
18
|
+
content = File.read(path)
|
19
|
+
File.open(path, 'w') do |f|
|
20
|
+
f.write Uglifier.compile(content)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
rescue LoadError
|
24
|
+
say('ERROR: please add the uglifier gem to your Gemfile to minfy javascripts', :red)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
unless options['skip-css']
|
29
|
+
begin
|
30
|
+
require 'yui/compressor'
|
31
|
+
Dir[build_dir.join('**/*.css')].each do |path|
|
32
|
+
content = File.read(path)
|
33
|
+
File.open(path, 'w') do |f|
|
34
|
+
f.write YUI::CssCompressor.new.compress(content)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
say('ERROR: please add the yui-compressor gem to your Gemfile to minfy css files', :red)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/tay/cli/new.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Tay
|
2
|
+
module CLI
|
3
|
+
class Root < ::Thor
|
4
|
+
desc 'new NAME', 'Create a new extension'
|
5
|
+
method_option 'no-gitignore', :type => :boolean, :default => false,
|
6
|
+
:banner => "Don\'t create a .gitignore file"
|
7
|
+
method_option 'no-gemfile', :type => :boolean, :default => false,
|
8
|
+
:banner => "Don\'t create a Gemfile file"
|
9
|
+
method_option 'use-coffeescript', :type => :boolean, :default => false,
|
10
|
+
:banner => "Use coffeescript"
|
11
|
+
method_option 'use-haml', :type => :boolean, :default => false,
|
12
|
+
:banner => "Use haml"
|
13
|
+
def new(name)
|
14
|
+
outdir = Pathname.new(Utils.filesystem_name(name))
|
15
|
+
create_directory_structure(outdir)
|
16
|
+
|
17
|
+
template('Gemfile', outdir.join('Gemfile')) unless options['no-gemfile']
|
18
|
+
copy_file('gitignore', outdir.join('.gitignore')) unless options['no-gitignore']
|
19
|
+
template('Tayfile', outdir.join('Tayfile'), {
|
20
|
+
'name' => name
|
21
|
+
}.merge(options))
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def create_directory_structure(outdir)
|
27
|
+
empty_directory(outdir)
|
28
|
+
empty_directory(outdir.join('src'))
|
29
|
+
empty_directory(outdir.join('src/assets'))
|
30
|
+
empty_directory(outdir.join('src/html'))
|
31
|
+
empty_directory(outdir.join('src/javascripts'))
|
32
|
+
empty_directory(outdir.join('src/stylesheets'))
|
33
|
+
empty_directory(outdir.join('src/templates'))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Tay
|
2
|
+
module CLI
|
3
|
+
class Root < ::Thor
|
4
|
+
desc 'package', 'Package the current extension'
|
5
|
+
method_option 'tayfile', :type => :string,
|
6
|
+
:banner => 'Use the specified tayfile instead of Tayfile'
|
7
|
+
method_option 'build-directory', :type => :string, :default => 'build',
|
8
|
+
:aliases => '-b', :banner => 'The directory containing the built extension'
|
9
|
+
method_option 'type', :type => 'string', :default => 'zip',
|
10
|
+
:aliases => '-t', :banner => 'The file type to build, zip or crx'
|
11
|
+
def package
|
12
|
+
unless %{zip crx} .include?(options['type'])
|
13
|
+
raise InvalidPackageType.new("Invalid package type '#{options['type']}'")
|
14
|
+
end
|
15
|
+
|
16
|
+
packager = Packager.new(spec, base_dir, build_dir)
|
17
|
+
|
18
|
+
if packager.private_key_exists?
|
19
|
+
say("Using private key at #{Utils.relative_path_to(packager.full_key_path)}", :green)
|
20
|
+
else
|
21
|
+
say("Creating private key at #{Utils.relative_path_to(packager.full_key_path)}", :yellow)
|
22
|
+
packager.write_new_key
|
23
|
+
end
|
24
|
+
|
25
|
+
empty_directory(base_dir.join('tmp'))
|
26
|
+
empty_directory(base_dir.join('pkg'))
|
27
|
+
|
28
|
+
temp_pkg_path = base_dir.join('tmp', 'package')
|
29
|
+
temp_pkg_path.unlink if temp_pkg_path.exist?
|
30
|
+
packager.send("write_#{options['type']}".to_sym, temp_pkg_path)
|
31
|
+
|
32
|
+
filename = Utils.filesystem_name(spec.name) + '-' + spec.version + '.' + options['type']
|
33
|
+
pkg_path = base_dir.join('pkg', filename)
|
34
|
+
|
35
|
+
copy_file(temp_pkg_path, pkg_path)
|
36
|
+
say("Wrote #{pkg_path.size} bytes to #{Utils.relative_path_to(pkg_path)}", :green)
|
37
|
+
temp_pkg_path.unlink
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'tay'
|
4
|
+
|
5
|
+
# You can make extensions with no extra gems, but tay works best when
|
6
|
+
# coupled with other langauges and tools. Uncomment them gems below
|
7
|
+
# then run "bundle install"
|
8
|
+
|
9
|
+
# Allows you to run "tay watch" to automatically recompile on change
|
10
|
+
# gem 'guard-tay'
|
11
|
+
|
12
|
+
<%= options['use-haml'] ? '' : '# ' %>gem 'haml'
|
13
|
+
# gem 'sass'
|
14
|
+
<%= options['use-coffeescript'] ? '' : '# ' %>gem 'coffee-script'
|
15
|
+
|
16
|
+
# Enable the usage .jst.mustache templates via Sprockets
|
17
|
+
# gem 'mustache-trimmer', :git => 'git://github.com/josh/mustache-trimmer.git'
|
18
|
+
|
19
|
+
# Enable the usage .jst.eco templates via Sprockets
|
20
|
+
# gem 'eco'
|
21
|
+
|
22
|
+
# Allows you to use CommonJS requires in your script files
|
23
|
+
# See https://github.com/maccman/sprockets-commonjs
|
24
|
+
# gem 'sprockets-commonjs', '0.0.5.pre', :require => 'sprockets/commonjs'
|
25
|
+
|
26
|
+
# Enable javascript compression via "tay minify"
|
27
|
+
# gem 'uglifier'
|
28
|
+
|
29
|
+
# Enable css compression via "tay minify"
|
30
|
+
# gem 'yui-compressor'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Tay::Specification.new do |ext|
|
2
|
+
ext.name = '<%= config['name'] %>'
|
3
|
+
ext.version = '0.0.1'
|
4
|
+
<% if config['browser-action'] %>
|
5
|
+
ext.stylesheets << 'stylesheets/browser_action.css'
|
6
|
+
ext.javascripts << 'javascripts/browser_action.js'
|
7
|
+
ext.add_browser_action do |ba|
|
8
|
+
ba.title = '<%= config['name'] %>'
|
9
|
+
ba.popup = 'html/browser_action.html'
|
10
|
+
# ba.icon = 'assets/browser_action_icon.png'
|
11
|
+
end
|
12
|
+
<% end -%>
|
13
|
+
<% if config['page-action'] %>
|
14
|
+
ext.permissions << 'tabs'
|
15
|
+
ext.background_scripts << 'javascripts/page_action_controller.js'
|
16
|
+
ext.add_page_action do |pa|
|
17
|
+
pa.title = '<%= config['name'] %>'
|
18
|
+
pa.icon = 'assets/page_action_icon.png'
|
19
|
+
# pa.popup = 'html/page_action.html'
|
20
|
+
end
|
21
|
+
<% end -%>
|
22
|
+
end
|