tay 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +135 -0
  5. data/Rakefile +6 -0
  6. data/bin/tay +15 -0
  7. data/lib/tay.rb +19 -0
  8. data/lib/tay/builder.rb +173 -0
  9. data/lib/tay/cli.rb +29 -0
  10. data/lib/tay/cli/build.rb +15 -0
  11. data/lib/tay/cli/generate.rb +73 -0
  12. data/lib/tay/cli/generators/browser_action.rb +20 -0
  13. data/lib/tay/cli/generators/content_script.rb +37 -0
  14. data/lib/tay/cli/generators/page_action.rb +19 -0
  15. data/lib/tay/cli/generators/templates/browser_action/action.css +4 -0
  16. data/lib/tay/cli/generators/templates/browser_action/action.html +11 -0
  17. data/lib/tay/cli/generators/templates/browser_action/action.js +5 -0
  18. data/lib/tay/cli/generators/templates/browser_action/tayfile +7 -0
  19. data/lib/tay/cli/generators/templates/content_script/content_script.css +6 -0
  20. data/lib/tay/cli/generators/templates/content_script/content_script.js +4 -0
  21. data/lib/tay/cli/generators/templates/content_script/tayfile +6 -0
  22. data/lib/tay/cli/generators/templates/page_action/controller.js +7 -0
  23. data/lib/tay/cli/generators/templates/page_action/icon.png +0 -0
  24. data/lib/tay/cli/generators/templates/page_action/tayfile +7 -0
  25. data/lib/tay/cli/helpers.rb +51 -0
  26. data/lib/tay/cli/minify.rb +44 -0
  27. data/lib/tay/cli/new.rb +37 -0
  28. data/lib/tay/cli/package.rb +41 -0
  29. data/lib/tay/cli/templates/Gemfile +30 -0
  30. data/lib/tay/cli/templates/Tayfile +22 -0
  31. data/lib/tay/cli/templates/gitignore +5 -0
  32. data/lib/tay/cli/validate.rb +21 -0
  33. data/lib/tay/cli/watch.rb +29 -0
  34. data/lib/tay/manifest_generator.rb +160 -0
  35. data/lib/tay/packager.rb +64 -0
  36. data/lib/tay/specification.rb +261 -0
  37. data/lib/tay/specification/action.rb +18 -0
  38. data/lib/tay/specification/browser_action.rb +10 -0
  39. data/lib/tay/specification/content_script.rb +41 -0
  40. data/lib/tay/specification/nacl_module.rb +18 -0
  41. data/lib/tay/specification/packaged_app.rb +33 -0
  42. data/lib/tay/specification/page_action.rb +10 -0
  43. data/lib/tay/specification/web_intent.rb +40 -0
  44. data/lib/tay/specification_validator.rb +167 -0
  45. data/lib/tay/utils.rb +21 -0
  46. data/lib/tay/version.rb +3 -0
  47. data/spec/spec_helper.rb +4 -0
  48. data/spec/tay_spec.rb +5 -0
  49. data/tay.gemspec +26 -0
  50. 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,4 @@
1
+ body {
2
+ padding: 20px;
3
+ font-family: Helvetica, Arial, sans-serif;
4
+ }
@@ -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,5 @@
1
+ document.addEventListener('DOMContentLoaded', function () {
2
+ var el = document.createElement('p');
3
+ el.appendChild(document.createTextNode('The time is now: ' + (new Date()).toTimeString()));
4
+ document.body.appendChild(el);
5
+ }, false);
@@ -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
+ h1 {
2
+ color: red !important;
3
+ }
4
+ h1:after {
5
+ content: " - color changed by content_script.css";
6
+ }
@@ -0,0 +1,4 @@
1
+ (function () {
2
+ var h1 = document.querySelector('h1');
3
+ h1.innerHTML = 'Set by content_script.js';
4
+ }());
@@ -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
@@ -0,0 +1,7 @@
1
+ chrome.tabs.onUpdated.addListener(function (tabId, changed, info) {
2
+ chrome.pageAction.show(tabId);
3
+ });
4
+
5
+ chrome.pageAction.onClicked.addListener(function (tab) {
6
+ alert('The page action was clicked on tab: ' + tab.title)
7
+ });
@@ -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
@@ -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