yellow-brick-road 0.2.2 → 0.2.3

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 (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']);