tay 0.0.2

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.
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