embork 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +5 -0
  7. data/TODO.md +16 -0
  8. data/bin/embork +63 -0
  9. data/blueprint/Borkfile +42 -0
  10. data/blueprint/Gemfile +13 -0
  11. data/blueprint/README.md +25 -0
  12. data/blueprint/app/app.js +11 -0
  13. data/blueprint/app/components/.gitkeep +0 -0
  14. data/blueprint/app/controllers/.gitkeep +0 -0
  15. data/blueprint/app/helpers/.gitkeep +0 -0
  16. data/blueprint/app/index.html.erb +18 -0
  17. data/blueprint/app/initializers/.gitkeep +0 -0
  18. data/blueprint/app/mixins/.gitkeep +0 -0
  19. data/blueprint/app/models/.gitkeep +0 -0
  20. data/blueprint/app/router.js +8 -0
  21. data/blueprint/app/routes/.gitkeep +0 -0
  22. data/blueprint/app/routes/index.js +1 -0
  23. data/blueprint/app/styles/.gitkeep +0 -0
  24. data/blueprint/app/styles/app.scss +3 -0
  25. data/blueprint/app/templates/.gitkeep +0 -0
  26. data/blueprint/app/templates/application.hbs +3 -0
  27. data/blueprint/app/templates/components/.gitkeep +0 -0
  28. data/blueprint/app/utils/.gitkeep +0 -0
  29. data/blueprint/app/views/.gitkeep +0 -0
  30. data/blueprint/bower.json +16 -0
  31. data/blueprint/bowerrc +3 -0
  32. data/blueprint/config/development/application.css +0 -0
  33. data/blueprint/config/development/application.js +12 -0
  34. data/blueprint/config/production/application.css +0 -0
  35. data/blueprint/config/production/application.js +12 -0
  36. data/blueprint/dotfiles +3 -0
  37. data/blueprint/erbfiles +5 -0
  38. data/blueprint/gitignore +17 -0
  39. data/blueprint/jshintrc +40 -0
  40. data/blueprint/package.json +15 -0
  41. data/blueprint/static/.gitkeep +0 -0
  42. data/blueprint/tests/.jshintrc +71 -0
  43. data/blueprint/tests/helpers/resolver.js +7 -0
  44. data/blueprint/tests/helpers/start-app.js +29 -0
  45. data/blueprint/tests/index.html +44 -0
  46. data/blueprint/tests/test-helper.js +6 -0
  47. data/blueprint/tests/test-loader.js +8 -0
  48. data/blueprint/tests/unit/.gitkeep +0 -0
  49. data/embork.gemspec +41 -0
  50. data/lib/embork.rb +23 -0
  51. data/lib/embork/borkfile.rb +148 -0
  52. data/lib/embork/build_versions.rb +21 -0
  53. data/lib/embork/builder.rb +156 -0
  54. data/lib/embork/environment.rb +90 -0
  55. data/lib/embork/forwarder.rb +23 -0
  56. data/lib/embork/generator.rb +184 -0
  57. data/lib/embork/logger.rb +40 -0
  58. data/lib/embork/pushstate.rb +16 -0
  59. data/lib/embork/server.rb +80 -0
  60. data/lib/embork/sprockets.rb +6 -0
  61. data/lib/embork/sprockets/ember_handlebars_compiler.rb +75 -0
  62. data/lib/embork/sprockets/es6_module_transpiler.rb +120 -0
  63. data/lib/embork/sprockets/frameworks.rb +34 -0
  64. data/lib/embork/sprockets/helpers.rb +45 -0
  65. data/lib/embork/sprockets/support/es6-module-transpiler.js +7190 -0
  66. data/lib/embork/sprockets/support/node_runner.js +22 -0
  67. data/lib/embork/version.rb +3 -0
  68. data/lib/string/strip.rb +27 -0
  69. data/spec/embork/borkfile/Borkfile.empty +0 -0
  70. data/spec/embork/borkfile/Borkfile.full +32 -0
  71. data/spec/embork/borkfile/Borkfile.rack +5 -0
  72. data/spec/embork/borkfile/Borkfile.relative +3 -0
  73. data/spec/embork/borkfile_spec.rb +119 -0
  74. data/spec/embork/builder/Borkfile +20 -0
  75. data/spec/embork/builder/app/index.html.erb +9 -0
  76. data/spec/embork/builder/config/production/application.css +0 -0
  77. data/spec/embork/builder/config/production/application.js +0 -0
  78. data/spec/embork/builder/config/production/deeply/nested/asset.js +0 -0
  79. data/spec/embork/builder/static/images/image.png +0 -0
  80. data/spec/embork/builder_spec.rb +95 -0
  81. data/spec/embork/environment_spec.rb +78 -0
  82. data/spec/embork/generator_spec.rb +84 -0
  83. data/spec/embork/server/example_app/Borkfile +1 -0
  84. data/spec/embork/server/example_app/app/app.js.erb +3 -0
  85. data/spec/embork/server/example_app/app/css/main.sass +3 -0
  86. data/spec/embork/server/example_app/app/index.html +9 -0
  87. data/spec/embork/server/example_app/build/development/application-12345.js +14 -0
  88. data/spec/embork/server/example_app/build/development/index.html +9 -0
  89. data/spec/embork/server/example_app/components/some/component.js +6 -0
  90. data/spec/embork/server/example_app/config/development/application.css +4 -0
  91. data/spec/embork/server/example_app/config/development/application.js +2 -0
  92. data/spec/embork/server/example_app/config/production/application.css +4 -0
  93. data/spec/embork/server/example_app/config/production/application.js +4 -0
  94. data/spec/embork/server/example_app/static/fonts/.gitkeep +0 -0
  95. data/spec/embork/server/example_app/static/images/.gitkeep +0 -0
  96. data/spec/embork/server/example_app/static/images/image.png +0 -0
  97. data/spec/embork/server/specimen.css +7 -0
  98. data/spec/embork/server/specimen.js +14 -0
  99. data/spec/embork/server_spec.rb +152 -0
  100. data/spec/embork/sprockets/ember_handlebars_compiler/amd_template.js +26 -0
  101. data/spec/embork/sprockets/ember_handlebars_compiler/cjs_template.js +24 -0
  102. data/spec/embork/sprockets/ember_handlebars_compiler/global_handlebars_template.js +17 -0
  103. data/spec/embork/sprockets/ember_handlebars_compiler/global_hbs_template.js +17 -0
  104. data/spec/embork/sprockets/ember_handlebars_compiler/my/hbs/template.hbs +5 -0
  105. data/spec/embork/sprockets/ember_handlebars_compiler/my_handlebars_template.js.handlebars +5 -0
  106. data/spec/embork/sprockets/ember_handlebars_compiler/my_hbs_template.js.hbs +5 -0
  107. data/spec/embork/sprockets/ember_handlebars_compiler/transformed_template.js +26 -0
  108. data/spec/embork/sprockets/ember_handlebars_compiler_spec.rb +82 -0
  109. data/spec/embork/sprockets/es6_module_transpiler/app/my/transformed/module.js +13 -0
  110. data/spec/embork/sprockets/es6_module_transpiler/app/my_fancy_module.js +13 -0
  111. data/spec/embork/sprockets/es6_module_transpiler/compiled_amd.js +20 -0
  112. data/spec/embork/sprockets/es6_module_transpiler/compiled_cjs.js +20 -0
  113. data/spec/embork/sprockets/es6_module_transpiler/component.js +1 -0
  114. data/spec/embork/sprockets/es6_module_transpiler/components/some_component.js +1 -0
  115. data/spec/embork/sprockets/es6_module_transpiler/config/application.js +1 -0
  116. data/spec/embork/sprockets/es6_module_transpiler/manifest.js +20 -0
  117. data/spec/embork/sprockets/es6_module_transpiler/namespaced.js +20 -0
  118. data/spec/embork/sprockets/es6_module_transpiler/transformed.js +20 -0
  119. data/spec/embork/sprockets/es6_module_transpiler_spec.rb +97 -0
  120. data/spec/spec_helper.rb +13 -0
  121. metadata +468 -0
@@ -0,0 +1,21 @@
1
+ module Embork::BuildVersions
2
+ VERSION_FORMAT_EXP = /\d{4}\.\d{2}\.\d{2}\.\d{2}\.\d{2}\.\d{2}\.\d{4}/
3
+
4
+ def sorted_versions(project_root)
5
+ build_path = File.join(project_root, 'build', Embork.env.to_s)
6
+
7
+ versions = []
8
+ Find.find(build_path) do |file|
9
+ version = version_name(file)
10
+ versions.push version if version
11
+ end
12
+
13
+ # Tidy up!
14
+ versions.uniq!.sort!.reverse!
15
+ end
16
+
17
+ def version_name(filename)
18
+ m = File.basename(filename).match VERSION_FORMAT_EXP
19
+ m.nil? ? false : m[0]
20
+ end
21
+ end
@@ -0,0 +1,156 @@
1
+ require 'pathname'
2
+ require 'fileutils'
3
+ require 'find'
4
+ require 'sprockets'
5
+
6
+ require 'embork/environment'
7
+ require 'embork/build_versions'
8
+
9
+ class Embork::Builder
10
+ include Embork::BuildVersions
11
+
12
+ def initialize(borkfile)
13
+ @borkfile = borkfile
14
+ @project_root = @borkfile.project_root
15
+ end
16
+
17
+ def build
18
+ @environment = Embork::Environment.new(@borkfile)
19
+ @sprockets_environment = @environment.sprockets_environment
20
+
21
+ @version = Time.now.to_s.gsub(/( -|-| |:)/, '.')
22
+
23
+ @sprockets_environment.context_class.use_bundled_assets = true
24
+ @sprockets_environment.context_class.bundled_version = @version
25
+
26
+ Dir.chdir @project_root do
27
+ config_path = File.join 'config', Embork.env.to_s
28
+ build_path = File.join 'build', Embork.env.to_s
29
+
30
+ asset_list = generate_asset_list config_path
31
+
32
+ manifest_path = File.join build_path, 'manifest.json'
33
+ manifest = Sprockets::Manifest.new(@sprockets_environment, manifest_path)
34
+ manifest.compile(asset_list)
35
+
36
+ # version assets
37
+ asset_list.each do |asset|
38
+ digested_name = manifest.assets[asset]
39
+ gzipped_name = "%s%s" % [ digested_name, '.gz' ]
40
+ versioned_name = generate_versioned_name(asset)
41
+
42
+ # Do the actual renaming and removing of the gzipped file.
43
+ # nginx handles gzipping just fine
44
+ Dir.chdir build_path do
45
+ File.rename digested_name, versioned_name
46
+ FileUtils.rm gzipped_name
47
+ end
48
+ end
49
+
50
+ # Link the index file since, chances are, you don't want to reconfigure
51
+ # your index file every time you deploy.
52
+ Dir.chdir build_path do
53
+ @borkfile.html.each do |file|
54
+ dirname = File.dirname file
55
+ extname = File.extname file
56
+ basename = File.basename file, extname
57
+ src_format = [ File.join(dirname, basename), @version, extname ]
58
+ FileUtils.ln_sf(("%s-%s%s" % src_format), file)
59
+ end
60
+ end if @borkfile.backend == :static_index
61
+
62
+ static_path = 'static'
63
+ static_pathname = Pathname.new static_path
64
+ static_directories = []
65
+ static_files = []
66
+ Find.find(static_path) do |file|
67
+ relative_name = Pathname.new(file).relative_path_from(static_pathname)
68
+ if FileTest.directory? file
69
+ static_directories.push relative_name
70
+ else
71
+ static_files.push relative_name
72
+ end
73
+ end
74
+
75
+ static_directories.each do |dir|
76
+ Dir.chdir(build_path) { FileUtils.mkdir_p dir }
77
+ end
78
+
79
+ static_files.each do |file|
80
+ src = File.join static_path, file
81
+ dest = File.join build_path, file
82
+
83
+ FileUtils.cp src, dest
84
+ end
85
+
86
+ # Clean up
87
+ FileUtils.rm manifest_path
88
+ end
89
+
90
+ @version
91
+ end
92
+
93
+ def clean
94
+ versions = sorted_versions @project_root
95
+
96
+ # If there are more than our threshold
97
+ if versions.length > @borkfile.keep_old_versions
98
+
99
+ # Grab the versions to keep
100
+ retained_versions = versions[0...@borkfile.keep_old_versions]
101
+ build_path = File.join(@project_root, 'build', Embork.env.to_s)
102
+
103
+ Find.find(build_path) do |file|
104
+ name = File.basename(file)
105
+
106
+ # Skip if this is an unversioned file
107
+ next unless version_name(file)
108
+
109
+ # If any version strings that we should retain are in the file name,
110
+ # skip to next. Otherwise, obliterate.
111
+ if retained_versions.any?{ |version| name.include?(version) }
112
+ next
113
+ else
114
+ Dir.chdir(build_path){ FileUtils.rm file }
115
+ end
116
+ end
117
+ end
118
+
119
+ end
120
+
121
+ def clean!
122
+ FileUtils.rm_rf File.join(@project_root, 'build', Embork.env.to_s)
123
+ end
124
+
125
+ protected
126
+
127
+ def generate_asset_list(config_path)
128
+ config_pathname = Pathname.new config_path
129
+
130
+ assets = []
131
+
132
+ # Add configged assets
133
+ Find.find(config_path) do |file|
134
+ if FileTest.directory? file
135
+ next
136
+ else
137
+ assets.push Pathname.new(file).relative_path_from(config_pathname).to_s
138
+ end
139
+ end
140
+
141
+ # Optionally add an index. This should probably actually rely on a config
142
+ # paramater in the borkfile listing out the html files to build.
143
+ assets.concat @borkfile.html
144
+
145
+ assets
146
+ end
147
+
148
+ def generate_versioned_name(asset_name)
149
+ ext = File.extname asset_name
150
+ dirname = File.dirname asset_name
151
+ filename = File.basename asset_name, ext
152
+
153
+ File.join dirname, ("%s-%s%s" % [ filename, @version, ext ])
154
+ end
155
+
156
+ end
@@ -0,0 +1,90 @@
1
+ require 'embork/sprockets'
2
+ require 'sprockets'
3
+
4
+ class Embork::Environment
5
+ include Embork::Sprockets::Frameworks
6
+
7
+ attr_reader :sprockets_environment
8
+ attr_reader :bundle_version
9
+ attr_reader :use_bundled_assets
10
+
11
+ class ErblessCache < Sprockets::Cache::FileStore
12
+ def []=(key, value)
13
+ # This is ugly, but it keeps ERB fresh
14
+ if value.has_key?('pathname') && value["pathname"].match(/\.erb($|\.)/)
15
+ value
16
+ else
17
+ super
18
+ end
19
+ end
20
+ end
21
+
22
+ def initialize(borkfile, options = {})
23
+ @borkfile = borkfile
24
+
25
+ setup_sprockets
26
+
27
+ if !@borkfile.es6_namespace.nil?
28
+ Embork::Sprockets::ES6ModuleTranspiler.namespace = @borkfile.es6_namespace
29
+ Embork::Sprockets::EmberHandlebarsCompiler.namespace = @borkfile.es6_namespace
30
+ end
31
+ end
32
+
33
+ def setup_sprockets
34
+ @sprockets_environment = Sprockets::Environment.new @borkfile.project_root
35
+ cache_path = File.join @borkfile.project_root, '.cache'
36
+ @sprockets_environment.cache = ErblessCache.new(cache_path)
37
+
38
+ setup_sprockets_defaults
39
+
40
+ setup_paths
41
+ setup_helpers
42
+ setup_processors
43
+ setup_engines
44
+ setup_frameworks
45
+ end
46
+
47
+ def setup_sprockets_defaults
48
+ @sprockets_environment.register_postprocessor 'application/javascript', Embork::Sprockets::ES6ModuleTranspiler
49
+ @sprockets_environment.register_engine '.hbs', Embork::Sprockets::EmberHandlebarsCompiler
50
+ @sprockets_environment.register_engine '.handlebars', Embork::Sprockets::EmberHandlebarsCompiler
51
+ end
52
+
53
+ def setup_paths
54
+ @borkfile.asset_paths.each do |path|
55
+ @sprockets_environment.append_path path
56
+ end
57
+ end
58
+
59
+ def setup_helpers
60
+ @borkfile.helpers.each do |helper_proc|
61
+ Embork::Sprockets::Helpers.class_eval &helper_proc
62
+ end
63
+ @sprockets_environment.context_class.class_eval do
64
+ include Embork::Sprockets::Helpers
65
+ extend Embork::Sprockets::Helpers::ClassMethods
66
+ end
67
+ end
68
+
69
+ def setup_processors
70
+ @borkfile.sprockets_postprocessors.each do |processor|
71
+ @sprockets_environment.register_postprocessor processor[:mime_type], processor[:klass]
72
+ end
73
+ @borkfile.sprockets_preprocessors.each do |processor|
74
+ @sprockets_environment.register_preprocessor processor[:mime_type], processor[:klass]
75
+ end
76
+ end
77
+
78
+ def setup_engines
79
+ @borkfile.sprockets_engines.each do |engine|
80
+ @sprockets_environment.register_engine engine[:extension], engine[:klass]
81
+ end
82
+ end
83
+
84
+ def setup_frameworks
85
+ @borkfile.frameworks.each do |framework|
86
+ method = ('load_%s_framework' % framework).to_sym
87
+ self.send method, @sprockets_environment
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,23 @@
1
+ class Embork::Forwarder
2
+ def self.target
3
+ @target
4
+ end
5
+
6
+ def self.target=(target)
7
+ @target = target
8
+ end
9
+
10
+ attr_reader :app
11
+ def initialize(app, options = {})
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ status, headers, body = @app.call(env)
17
+ if status == 404
18
+ self.class.target.new(@app).call(env)
19
+ else
20
+ [ status, headers, body ]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,184 @@
1
+ require 'pathname'
2
+ require 'erb'
3
+ require 'open3'
4
+
5
+ require 'embork/logger'
6
+
7
+ class Embork::Generator
8
+ attr_reader :erb_files
9
+ attr_reader :dot_files
10
+ attr_reader :project_path
11
+
12
+ BLUEPRINT_DIR=File.expand_path('../../../blueprint', __FILE__).freeze
13
+
14
+ def initialize(package_name, options)
15
+ @package_name = package_name
16
+ @logger = Embork::Logger.new STDOUT, :simple
17
+ read_erb_files
18
+ read_dot_files
19
+ set_project_path(options[:directory])
20
+ end
21
+
22
+ def read_erb_files
23
+ list_file_path = File.join(BLUEPRINT_DIR, 'erbfiles')
24
+ @erb_files = File.readlines(list_file_path).map{ |f| f.strip }
25
+ end
26
+
27
+ def read_dot_files
28
+ list_file_path = File.join(BLUEPRINT_DIR, 'dotfiles')
29
+ @dot_files = File.readlines(list_file_path).map{ |f| f.strip }
30
+ end
31
+
32
+ def set_project_path(directory)
33
+ if directory.nil?
34
+ @project_path = File.join Dir.pwd, @package_name
35
+ else
36
+ p = Pathname.new directory
37
+ if p.absolute?
38
+ @project_path = p.to_s
39
+ else
40
+ @project_path = File.expand_path p.to_s, Dir.pwd
41
+ end
42
+ end
43
+ end
44
+
45
+ def generate
46
+ check_for_npm
47
+ print_banner
48
+ copy_files
49
+ process_erb
50
+ move_dot_files
51
+ install_npm_deps
52
+ install_bower_deps
53
+ bundle
54
+ init_git
55
+ print_success
56
+ end
57
+
58
+ protected
59
+
60
+ attr_reader :logger
61
+
62
+ def check_for_npm
63
+ status = Open3.popen3('which npm') do |stdin, stdout, stderr, wait_thr|
64
+ stdin.close
65
+ wait_thr.value
66
+ end
67
+ if !status.success?
68
+ logger.fatal :banner
69
+ logger.warn "Hey Person! Embork needs node and npm installed to work properly."
70
+ logger.warn "Come back and try again when you get them set up!"
71
+ logger.fatal :banner
72
+ exit 1
73
+ end
74
+ end
75
+
76
+ def copy_files
77
+ FileUtils.mkdir_p project_path
78
+ FileUtils.cp_r File.join(BLUEPRINT_DIR, '.'), project_path
79
+ end
80
+
81
+ class ErbHelpers
82
+ attr_accessor :namespace
83
+
84
+ def get_binding
85
+ binding
86
+ end
87
+ end
88
+
89
+ def process_erb
90
+ helpers = ErbHelpers.new
91
+ helpers.namespace = @package_name
92
+ Dir.chdir project_path do
93
+ erb_files.each do |file|
94
+ processed_file = ERB.new(File.read(file)).result helpers.get_binding
95
+ File.open(file, 'w'){ |f| f.write processed_file }
96
+ end
97
+ end
98
+ end
99
+
100
+ def move_dot_files
101
+ Dir.chdir project_path do
102
+ dot_files.each do |file|
103
+ FileUtils.mv file, '.%s' % file
104
+ end
105
+ end
106
+ end
107
+
108
+ def install_npm_deps
109
+ logger.info 'Fetching npm dependencies.'
110
+ command = 'npm install'
111
+ status, out = run_in_project_dir command
112
+ print_error(command, out) unless status.success?
113
+ end
114
+
115
+ def install_bower_deps
116
+ logger.info 'Fetching bower dependencies.'
117
+ command = 'npm run bower-deps'
118
+ status, out = run_in_project_dir command
119
+ print_error(command, out) unless status.success?
120
+ end
121
+
122
+ def bundle
123
+ logger.info 'Bundling app.'
124
+ command = 'bundle install'
125
+ # Clean up bundler before running bundle
126
+ bundle_vars = %w(BUNDLE_GEMFILE RUBYOPT BUNDLE_BIN_PATH)
127
+ bundled_env = ENV.to_hash
128
+ bundle_vars.each{ |var| ENV.delete var }
129
+
130
+ # Run bundle
131
+ status, out = run_in_project_dir command
132
+
133
+ # Restor bundler
134
+ ENV.replace bundled_env
135
+ print_error(command, out) unless status.success?
136
+ end
137
+
138
+ def init_git
139
+ command = 'git init'
140
+ status, out = run_in_project_dir command
141
+ print_error(command, out) unless status.success?
142
+ end
143
+
144
+ def run_in_project_dir(command)
145
+ out = status = nil
146
+ Dir.chdir project_path do
147
+ out = ''
148
+ status = Open3.popen3(command) do |stdin, stdout, stderr, wait_thr|
149
+ stdin.close
150
+ out = stdout.read + stderr.read
151
+ wait_thr.value
152
+ end
153
+ end
154
+ [ status, out ]
155
+ end
156
+
157
+ def print_error(command, trace)
158
+ logger.fatal :banner
159
+ logger.warn "The command '%s' failed to run." % command
160
+ logger.debug "It failed with the following error:"
161
+ logger.fatal :banner
162
+ logger.debug trace
163
+ exit 1
164
+ end
165
+
166
+ def print_banner
167
+ logger.unknown :banner
168
+ logger.info 'Setting up new embork project %s.' % @package_name
169
+ logger.unknown :banner
170
+ logger.unknown ''
171
+ end
172
+
173
+ def print_success
174
+ logger.unknown :banner
175
+ logger.info "Project setup in:"
176
+ logger.unknown project_path.dup.prepend ' '
177
+ logger.unknown ''
178
+ logger.info "Your Embork project is ready to rock!"
179
+ logger.info "`cd` into the project directory and type `embork server` to get started."
180
+ logger.unknown :banner
181
+ logger.unknown ''
182
+ end
183
+
184
+ end