yellow-brick-road 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/README.rst +9 -1
  2. data/Rakefile +0 -3
  3. data/lib/generators/templates/yellow_brick_road.rb.erb +12 -0
  4. data/lib/tasks/ybr.rake +12 -0
  5. data/lib/yellow-brick-road.rb +5 -0
  6. data/lib/yellow-brick-road/config.rb +45 -6
  7. data/lib/yellow-brick-road/directive_processor.rb +89 -10
  8. data/lib/yellow-brick-road/engine.rb +10 -0
  9. data/lib/yellow-brick-road/protobuf_js.rb +32 -0
  10. data/lib/yellow-brick-road/soy_processor.rb +13 -4
  11. data/lib/yellow-brick-road/utils.rb +7 -1
  12. data/lib/yellow-brick-road/version.rb +1 -1
  13. data/test/dummy/app/assets/javascripts/application.js +1 -0
  14. data/test/dummy/app/assets/javascripts/closure-deps.js +2 -1
  15. data/test/dummy/app/assets/javascripts/protos/person.pb.js +207 -0
  16. data/test/dummy/app/protos/person.proto +5 -0
  17. data/test/dummy/log/development.log +1544 -0
  18. data/test/dummy/tmp/cache/assets/C5B/240/sprockets%2Fc561864da49634b1e8464990f63f4123 +314 -0
  19. data/test/dummy/tmp/cache/assets/C7E/9F0/sprockets%2F89862076204c62c4593ac20de32da909 +6 -5
  20. data/test/dummy/tmp/cache/assets/CBD/850/sprockets%2F9191c7b83dca8e9342628ac59e452229 +297 -0
  21. data/test/dummy/tmp/cache/assets/CCC/BB0/sprockets%2F649c7cc1e706997576646e6dd790d7a0 +0 -0
  22. data/test/dummy/tmp/cache/assets/CE0/AB0/sprockets%2Fb8f01070d8f72dd30306684ef61858ac +204 -0
  23. data/test/dummy/tmp/cache/assets/CF7/BC0/sprockets%2Fe47129798756fd8f35bd4350bff5e461 +213 -0
  24. data/test/dummy/tmp/cache/assets/D15/F60/sprockets%2Fa28394e3f80365b5bc86794dd46daa22 +0 -0
  25. data/test/dummy/tmp/cache/assets/D50/F20/sprockets%2Fd858e852254b667a8efffa4f12d96d11 +0 -0
  26. data/test/dummy/tmp/cache/assets/D6B/0C0/sprockets%2F8c3bdd9c000f7f5a26e91f294a71c3c4 +0 -0
  27. data/test/dummy/tmp/cache/assets/D6F/6D0/sprockets%2Ff9f65ec20235e6595b5eb2ab91f15bb4 +1441 -0
  28. data/test/dummy/tmp/cache/assets/D84/210/sprockets%2Fabd0103ccec2b428ac62c94e4c40b384 +7 -5
  29. data/test/dummy/tmp/cache/assets/D97/E60/sprockets%2F18762119fe3a03903efaac2bfceec628 +763 -0
  30. data/test/dummy/tmp/cache/assets/DA1/670/sprockets%2Fccb4ba5dcd2f7696c636666ca5ab6057 +60 -0
  31. data/test/dummy/tmp/cache/assets/DED/040/sprockets%2Fd3aa2ab8d25cde3b6fb324dbb8c42933 +746 -0
  32. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  33. metadata +38 -11
  34. data/lib/tasks/yellow-brick-road_tasks.rake +0 -4
data/README.rst CHANGED
@@ -11,6 +11,8 @@ Yellow-brick-road is a set of tools to integrate google `closure library <http:/
11
11
 
12
12
  * Automatic dependency generation of a closure library based application, just add the ``//= require_closure_root`` directive.
13
13
 
14
+ * Compiling protocol buffer files to closure library ``goog.proto2.Message`` subclasses, as a rake task.
15
+
14
16
  * Using soy templates as part of the closure library.
15
17
 
16
18
  * Using stand-alone soy templates without closure library, just configure the gem add the ``.js.soy`` file in assets directory, and it gets compiled automatically.
@@ -23,13 +25,19 @@ Setup
23
25
  To use yellow-brick-road in rails, add these gems to ``Gemfile``:
24
26
 
25
27
  ::
28
+
29
+ # To enable protocol buffer support.
30
+ # Add this gem _before_ yellow-brick-road.
31
+ gem 'protobuf-closure-library'
26
32
 
27
33
  gem 'yellow-brick-road'
34
+
35
+ # To use internal closure library.
28
36
  gem 'closure-library-wrapper',
29
37
  :git => 'git://github.com/alitn/closure-library-wrapper.git',
30
38
  :submodules => true
31
39
 
32
- When an external closure library source is used, the second gem is not necessary.
40
+ When an external closure library source is used, ``closure-library-wrapper`` gem is not necessary.
33
41
 
34
42
  Configuration
35
43
  +++++++++++++
data/Rakefile CHANGED
@@ -20,8 +20,6 @@ RDoc::Task.new(:rdoc) do |rdoc|
20
20
  rdoc.rdoc_files.include('lib/**/*.rb')
21
21
  end
22
22
 
23
-
24
-
25
23
  Bundler::GemHelper.install_tasks
26
24
 
27
25
  require 'rake/testtask'
@@ -33,5 +31,4 @@ Rake::TestTask.new(:test) do |t|
33
31
  t.verbose = false
34
32
  end
35
33
 
36
-
37
34
  task :default => :test
@@ -12,8 +12,20 @@ YellowBrickRoad.setup do |config|
12
12
  # When this options is used, the above commit-id lock will be ignored.
13
13
  # config.closure_library_root = '/path/to/your/closure-library-root'
14
14
 
15
+ # Set a namespace or an array of namespaces of your closure
16
+ # app to be passed to closurebuilder.py, see:
17
+ # http://code.google.com/closure/library/docs/closurebuilder.html
18
+ # This a required options when Rails.application.config.assets.debug
19
+ # is set to false.
20
+ # config.closure_namespace = 'your.closure.namespace'
21
+
15
22
  # Uncomment this to use yellow-brick-road as an standalone
16
23
  # soy template compiler. If this option is used, the output
17
24
  # of the compiler will be different -- see the documentation.
18
25
  # config.standalone_soy = true
26
+
27
+ # Uncomment this to not clear asset cache on application start.
28
+ # It is recommended to set this option to true to avoid confolicts
29
+ # in closure applications raise by stale cache.
30
+ # config.clear_asset_cache_on_startup = false
19
31
  end
@@ -0,0 +1,12 @@
1
+ namespace :ybr do
2
+
3
+ if YellowBrickRoad.protobuf_enabled
4
+ desc 'Compile protocol buffer files.'
5
+ task :compile_protos do
6
+ initializer = Rails.root.join 'config', 'initializers', 'yellow_brick_road.rb'
7
+ require initializer
8
+ YellowBrickRoad.compile_protos Logger.new(STDOUT)
9
+ end
10
+ end
11
+
12
+ end
@@ -1,6 +1,11 @@
1
1
  require 'yellow-brick-road/version'
2
2
  require 'yellow-brick-road/config'
3
3
  require 'yellow-brick-road/utils'
4
+ begin
5
+ require 'protobuf-closure-library'
6
+ require 'yellow-brick-road/protobuf_js'
7
+ rescue LoadError
8
+ end
4
9
  require 'yellow-brick-road/directive_processor'
5
10
  require 'yellow-brick-road/soy_processor'
6
11
  require 'yellow-brick-road/engine'
@@ -7,8 +7,12 @@ module YellowBrickRoad
7
7
  VENDOR_ROOT = File.join ROOT, 'vendor'
8
8
 
9
9
  CLOSURE_LIBRARY_ROOT_INTERNAL = ClosureLibraryWrapper.closure_library_root
10
- CLOSURE_LIBRARY_BASE_RELPATH = ['closure', 'goog', 'base.js']
10
+ CLOSURE_LIBRARY_GOOG_RELPATH = ['closure', 'goog']
11
+ CLOSURE_LIBRARY_THIRD_PARTY_RELPATH = ['third_party', 'closure', 'goog']
12
+ CLOSURE_LIBRARY_BASE_FILE_NAME = 'base.js'
13
+ CLOSURE_LIBRARY_DEPS_FILE_NAME = 'deps.js'
11
14
  CLOSURE_DEPSWRITER_RELPATH = ['closure', 'bin', 'build', 'depswriter.py']
15
+ CLOSURE_BUILDER_RELPATH = ['closure', 'bin', 'build', 'closurebuilder.py']
12
16
 
13
17
  CLOSURE_SOYUTILS_ROOT = File.join VENDOR_ROOT, 'closure-soyutils'
14
18
  CLOSURE_SOYUTILS_USEGOOG_ROOT = File.join VENDOR_ROOT, 'closure-soyutils-usegoog'
@@ -19,17 +23,48 @@ module YellowBrickRoad
19
23
 
20
24
  # Config.
21
25
 
22
- mattr_accessor :closure_library_root
23
- @@closure_library_root = CLOSURE_LIBRARY_ROOT_INTERNAL
24
-
25
26
  mattr_reader :closure_deps_writer
27
+ mattr_reader :closure_builder
28
+
29
+ mattr_reader :closure_library_goog
30
+ mattr_reader :closure_library_third_party
26
31
  mattr_reader :closure_library_base
32
+ mattr_reader :closure_library_deps
27
33
 
34
+ mattr_accessor :closure_library_root
35
+ @@closure_library_root = CLOSURE_LIBRARY_ROOT_INTERNAL
28
36
  def self.closure_library_root= value
29
37
  @@closure_library_root = value
30
38
  self.update_closure_library_properties
31
39
  end
32
40
 
41
+ mattr_accessor :closure_namespace
42
+ @@closure_namespace = ''
43
+
44
+ mattr_accessor :concat_closure_roots
45
+ def self.initClosureConfig
46
+ @@concat_closure_roots = !Rails.application.config.assets.debug
47
+ end
48
+
49
+ mattr_accessor :clear_asset_cache_on_startup
50
+ @@clear_asset_cache_on_startup = true
51
+
52
+ mattr_reader :protobuf_enabled
53
+ @@protobuf_enabled = false
54
+
55
+ mattr_accessor :protos_dir
56
+ mattr_accessor :protos_js_out_dir
57
+ def self.initProtos
58
+ @@protos_dir ||= Rails.root.join 'app', 'protos', '**', '*.proto'
59
+ @@protos_js_out_dir ||= Rails.root.join 'app', 'assets', 'javascripts', 'protos'
60
+ end
61
+
62
+ mattr_accessor :protobuf_js_superclass
63
+ @@protobuf_js_superclass = nil
64
+
65
+ mattr_accessor :protobuf_js_advanced
66
+ @@protobuf_js_advanced = false
67
+
33
68
  mattr_accessor :standalone_soy
34
69
  @@stand_alone_soy = false
35
70
 
@@ -41,11 +76,15 @@ module YellowBrickRoad
41
76
  yield self
42
77
  end
43
78
 
44
- private
79
+ private
45
80
 
46
81
  def self.update_closure_library_properties
47
82
  @@closure_deps_writer = File.join @@closure_library_root, *CLOSURE_DEPSWRITER_RELPATH
48
- @@closure_library_base = File.join @@closure_library_root, *CLOSURE_LIBRARY_BASE_RELPATH
83
+ @@closure_builder = File.join @@closure_library_root, *CLOSURE_BUILDER_RELPATH
84
+ @@closure_library_goog = File.join @@closure_library_root, *CLOSURE_LIBRARY_GOOG_RELPATH
85
+ @@closure_library_third_party = File.join @@closure_library_root, *CLOSURE_LIBRARY_THIRD_PARTY_RELPATH
86
+ @@closure_library_base = File.join @@closure_library_goog, CLOSURE_LIBRARY_BASE_FILE_NAME
87
+ @@closure_library_deps = File.join @@closure_library_goog, CLOSURE_LIBRARY_DEPS_FILE_NAME
49
88
  end
50
89
  self.update_closure_library_properties
51
90
 
@@ -3,16 +3,21 @@ require 'sprockets/directive_processor.rb'
3
3
  module YellowBrickRoad
4
4
  class ClosureBuilderProcessor < Sprockets::DirectiveProcessor
5
5
 
6
+ GOOG_BASE_REL_PATH = File.join '..', '..'
7
+
6
8
  def prepare
7
9
  super
8
10
  @closure_roots = []
9
11
  @closure_deps_file = Rails.root.join *CLOSURE_DEPS_FILE_RELPATH
10
12
  @closure_root_prefix = File.join '..', '..'
11
- @has_executed_closure_builder = false
13
+ @has_processed_closure_roots = false
12
14
  end
13
15
 
14
16
  def process_require_closure_root_directive path
15
- context.require_asset YellowBrickRoad.closure_library_base
17
+ if !YellowBrickRoad.concat_closure_roots
18
+ context.require_asset YellowBrickRoad.closure_library_base
19
+ context.require_asset YellowBrickRoad.closure_library_deps
20
+ end
16
21
  context.require_asset @closure_deps_file
17
22
 
18
23
  if relative? path
@@ -41,36 +46,110 @@ class ClosureBuilderProcessor < Sprockets::DirectiveProcessor
41
46
 
42
47
  def process_directives
43
48
  super
44
- generate_closure_dependencies
49
+ process_closure_roots
45
50
  end
46
51
 
47
52
  private
48
53
 
49
- def generate_closure_dependencies
50
- return nil if @closure_roots.empty? || @has_executed_closure_builder
54
+ def process_closure_roots
55
+ return nil if @closure_roots.empty? || @has_processed_closure_roots
51
56
 
52
57
  if !YellowBrickRoad.standalone_soy
53
- @closure_roots.unshift << {
58
+ @closure_roots.unshift ({
54
59
  path: CLOSURE_SOYUTILS_USEGOOG_ROOT,
55
- path_relative_to_goog_base: '/'
56
- }
60
+ path_relative_to_goog_base: GOOG_BASE_REL_PATH
61
+ })
62
+ end
63
+
64
+ if YellowBrickRoad.protobuf_enabled
65
+ context.depend_on YellowBrickRoad.protos_js_out_dir
66
+ @closure_roots.unshift ({
67
+ path: YellowBrickRoad.protos_js_out_dir,
68
+ path_relative_to_goog_base: File.join('..', '..')
69
+ })
57
70
  end
58
71
 
72
+ result = YellowBrickRoad.concat_closure_roots ?
73
+ generate_concat : generate_no_concat
74
+
75
+ @has_processed_closure_roots = true
76
+
77
+ result
78
+ end
79
+
80
+ def generate_no_concat
81
+ # Gather roots.
59
82
  closure_roots_with_prefix = @closure_roots.map { |cr| "'#{cr[:path]} #{cr[:path_relative_to_goog_base]}'" }
60
83
 
84
+ # Run depswriter.
61
85
  result = Utils::run_command YellowBrickRoad.closure_deps_writer,
62
86
  command_options: {
63
87
  root_with_prefix: closure_roots_with_prefix,
64
88
  output_file: @closure_deps_file
65
89
  },
66
90
  command_error_message: 'An error occured while running closure depswriter.py.'
91
+
92
+ # Clean up and report.
93
+ closure_roots = @closure_roots.map { |cr| cr[:path] }
94
+ Rails.logger.info "Executed closure depswriter.py on root paths: #{closure_roots.join(', ')}"
95
+
96
+ result
97
+ end
67
98
 
68
- @has_executed_closure_builder = true
69
- Rails.logger.info "Executed closure depswriter.py on root paths: #{@closure_roots.join(', ')}"
99
+ def generate_concat
100
+ # Check for namespace.
101
+ namespace = YellowBrickRoad.closure_namespace
102
+ if namespace.empty?
103
+ raise <<-FIN
104
+ No closure namespace was given. One or more input files to
105
+ calculate dependencies is required by closurebuilder.py. Set
106
+ a namespace or an array of namespaces to YellowBrickRoad.closure_namespace
107
+ in the initializer.
108
+ FIN
109
+ end
70
110
 
111
+ # Gather roots.
112
+ closure_roots = @closure_roots.map { |cr| cr[:path] }
113
+ closure_roots.unshift YellowBrickRoad.closure_library_third_party
114
+ closure_roots.unshift YellowBrickRoad.closure_library_goog
115
+
116
+ # Generate soy files.
117
+ soy_files = []
118
+ Rails.application.assets.each_file do |asset_file|
119
+ soy_files << asset_file.to_s if asset_file.extname == '.soy'
120
+ end
121
+ soy_out_dir = Dir.mktmpdir
122
+ compile_soy_templates soy_files, soy_out_dir
123
+ closure_roots << soy_out_dir
124
+
125
+ # Run closurebuilder.
126
+ result = Utils::run_command YellowBrickRoad.closure_builder,
127
+ command_options: {
128
+ root: closure_roots,
129
+ output_mode: 'script',
130
+ namespace: namespace,
131
+ output_file: @closure_deps_file
132
+ },
133
+ command_error_message: 'An error occured while running closurebuilder.py.'
134
+
135
+ # Clean up and report.
136
+ FileUtils.remove_entry_secure soy_out_dir
137
+ Rails.logger.info "Executed closurebuilder.py on root paths: #{closure_roots.join(', ')}"
71
138
 
72
139
  result
73
140
  end
74
141
 
142
+ def compile_soy_templates soy_files, out_dir
143
+ return if soy_files.empty?
144
+
145
+ result = Utils::run_command "java -jar #{CLOSURE_SOY_COMPILER}",
146
+ command_arg: soy_files.join(' '),
147
+ command_options: {
148
+ outputPathFormat: File.join(out_dir, '{INPUT_DIRECTORY}/{INPUT_FILE_NAME_NO_EXT}_{LOCALE_LOWER_CASE}.js'),
149
+ shouldProvideRequireSoyNamespaces: '',
150
+ },
151
+ command_error_message: 'An error occured while running closurebuilder.py.'
152
+ end
153
+
75
154
  end
76
155
  end
@@ -3,6 +3,11 @@ module YellowBrickRoad
3
3
  class Engine < Rails::Engine
4
4
 
5
5
  initializer :yellow_brick_road do |app|
6
+ if YellowBrickRoad.clear_asset_cache_on_startup
7
+ Rails.application.assets.cache.clear
8
+ end
9
+
10
+ YellowBrickRoad.initClosureConfig
6
11
  app.assets.append_path YellowBrickRoad.closure_library_root
7
12
 
8
13
  if YellowBrickRoad.standalone_soy
@@ -11,6 +16,11 @@ class Engine < Rails::Engine
11
16
  app.assets.append_path CLOSURE_SOYUTILS_USEGOOG_ROOT
12
17
  end
13
18
 
19
+ if YellowBrickRoad.protobuf_enabled
20
+ YellowBrickRoad.initProtos
21
+ app.assets.append_path YellowBrickRoad.protos_js_out_dir
22
+ end
23
+
14
24
  app.assets.unregister_processor 'application/javascript', Sprockets::DirectiveProcessor
15
25
  app.assets.register_processor 'application/javascript', ClosureBuilderProcessor
16
26
 
@@ -0,0 +1,32 @@
1
+
2
+ module YellowBrickRoad
3
+ @@protobuf_enabled = true
4
+ include ProtobufClosureLibrary
5
+
6
+ def self.compile_protos logger = Rails.logger
7
+ YellowBrickRoad.initProtos
8
+ proto_files = Dir[YellowBrickRoad.protos_dir]
9
+
10
+ if proto_files.empty?
11
+ logger.info "No protobuf file to compile in #{YellowBrickRoad.protos_dir}."
12
+ return
13
+ end
14
+
15
+ generator_options = {}
16
+ if YellowBrickRoad.protobuf_js_superclass
17
+ generator_options[:js_superclass] = YellowBrickRoad.protobuf_js_superclass
18
+ end
19
+ if YellowBrickRoad.protobuf_js_advanced
20
+ generator_options[:advanced] = 'true'
21
+ end
22
+
23
+ logger.info 'Compiling protobuf to closure-library javascript:'
24
+ proto_files.each do |proto_file|
25
+ logger.info "\t- #{proto_file}"
26
+ ProtocJs.compile proto_file, YellowBrickRoad.protos_js_out_dir,
27
+ generator_options: generator_options
28
+ end
29
+ logger.info "Compiled all to #{YellowBrickRoad.protos_js_out_dir}"
30
+ end
31
+
32
+ end
@@ -1,4 +1,5 @@
1
1
  require 'tilt'
2
+ require 'tempfile'
2
3
 
3
4
  module YellowBrickRoad
4
5
  class SoyProcessor < Tilt::Template
@@ -27,15 +28,23 @@ class SoyProcessor < Tilt::Template
27
28
  attr_reader :namespace
28
29
 
29
30
  def evaluate scope, locals, &block
31
+ # When concatenating closure code by closurebuilder,
32
+ # the soy processor should not function as it will lead to
33
+ # duplicated code.
34
+ # Completely unregistering the soy processor is not an option
35
+ # as we need to track the soy files assets.
36
+ return ';' if YellowBrickRoad.concat_closure_roots
37
+
30
38
  # Since SoyToJsSrcCompiler does not provide a stdout access to
31
39
  # the output, the output is written to a tempfile.
32
- tempoutput = Rails.root.join 'tmp', "soy-#{Time.now.to_i.to_s}.js"
33
- compiler_options= @compiler_options.merge outputPathFormat: tempoutput
40
+ # tempoutput = Rails.root.join 'tmp', "soy-#{Time.now.to_i.to_s}.js"
41
+ tempfile = Tempfile.new 'soy'
42
+ compiler_options = @compiler_options.merge outputPathFormat: tempfile.path
34
43
 
35
44
  compile compiler_options
36
45
 
37
- @output = IO.read tempoutput
38
- File.delete tempoutput
46
+ @output = IO.read tempfile.path
47
+ tempfile.unlink
39
48
 
40
49
  @output
41
50
  end
@@ -21,7 +21,13 @@ class Utils
21
21
  raise "#{options[:command_error_message]}\n\n#{error.message}"
22
22
  end
23
23
 
24
- stdout.readlines
24
+ err = stderr.readlines
25
+ if false# !err.empty?
26
+ err = err.join('')
27
+ # Wrap longs texts.
28
+ err.gsub!(/(.{1,#{120}})( +|$\n?)|(.{1,#{120}})/, "\\1\\3\n")
29
+ raise "#{options[:command_error_message]}\n\n#{err}"
30
+ end
25
31
  end
26
32
 
27
33
  private
@@ -1,3 +1,3 @@
1
1
  module YellowBrickRoad
2
- VERSION = '0.2.2'
2
+ VERSION = '0.2.3'
3
3
  end
@@ -7,6 +7,7 @@
7
7
  //= require jquery
8
8
  //= require jquery_ujs
9
9
  //= require_closure_root ./my-closure
10
+ //= require_closure_root ./protos
10
11
  //= require ./my-closure/simple.js.soy
11
12
  //= require ./my-closure/start
12
13
  //
@@ -1,4 +1,5 @@
1
1
  // This file was autogenerated by /Users/ali/.rvm/gems/ruby-1.9.3-p0/bundler/gems/closure-library-wrapper-031d1d0f0e50/vendor/closure-library/closure/bin/build/depswriter.py.
2
2
  // Please do not edit.
3
3
  goog.addDependency('../../my-closure/start.js', ['myproject.start'], ['goog.dom', 'myproject.templates']);
4
- goog.addDependency('/soyutils_usegoog.js', ['soy', 'soy.StringBuilder', 'soy.esc', 'soydata', 'soydata.SanitizedHtml', 'soydata.SanitizedHtmlAttribute', 'soydata.SanitizedJsStrChars', 'soydata.SanitizedUri'], ['goog.asserts', 'goog.dom.DomHelper', 'goog.format', 'goog.i18n.BidiFormatter', 'goog.i18n.bidi', 'goog.soy', 'goog.string', 'goog.string.StringBuffer']);
4
+ goog.addDependency('../../protos/person.pb.js', ['Person'], ['goog.proto2.Message']);
5
+ goog.addDependency('/../../../soyutils_usegoog.js', ['soy', 'soy.StringBuilder', 'soy.esc', 'soydata', 'soydata.SanitizedHtml', 'soydata.SanitizedHtmlAttribute', 'soydata.SanitizedJsStrChars', 'soydata.SanitizedUri'], ['goog.asserts', 'goog.dom.DomHelper', 'goog.format', 'goog.i18n.BidiFormatter', 'goog.i18n.bidi', 'goog.soy', 'goog.string', 'goog.string.StringBuffer']);