embork 0.0.4

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