spark_engine 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/CODE_OF_CONDUCT.md +49 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +34 -0
  7. data/Rakefile +2 -0
  8. data/bin/spark +99 -0
  9. data/lib/spark_engine/assets.rb +8 -0
  10. data/lib/spark_engine/command/help.rb +86 -0
  11. data/lib/spark_engine/command/npm.rb +62 -0
  12. data/lib/spark_engine/command.rb +156 -0
  13. data/lib/spark_engine/config_data.rb +29 -0
  14. data/lib/spark_engine/helpers/asset_helpers.rb +66 -0
  15. data/lib/spark_engine/helpers/layout_helpers.rb +21 -0
  16. data/lib/spark_engine/middleware.rb +72 -0
  17. data/lib/spark_engine/plugin/assets/asset.rb +163 -0
  18. data/lib/spark_engine/plugin/assets/javascripts.rb +83 -0
  19. data/lib/spark_engine/plugin/assets/stylesheets.rb +88 -0
  20. data/lib/spark_engine/plugin/assets/svgs.rb +79 -0
  21. data/lib/spark_engine/plugin.rb +191 -0
  22. data/lib/spark_engine/sass/engine.rb +21 -0
  23. data/lib/spark_engine/sass/importer.rb +103 -0
  24. data/lib/spark_engine/scaffold/gem/.gitignore +18 -0
  25. data/lib/spark_engine/scaffold/gem/app/assets/images/namespace/.keep +0 -0
  26. data/lib/spark_engine/scaffold/gem/app/assets/javascripts/namespace/engine.js +3 -0
  27. data/lib/spark_engine/scaffold/gem/app/assets/stylesheets/namespace/_index.scss +1 -0
  28. data/lib/spark_engine/scaffold/gem/app/assets/svgs/namespace/.keep +0 -0
  29. data/lib/spark_engine/scaffold/gem/app/helpers/namespace/application_helper.rb +4 -0
  30. data/lib/spark_engine/scaffold/gem/app/views/layouts/namespace/default.html.erb +18 -0
  31. data/lib/spark_engine/scaffold/gem/gem.gemspec +24 -0
  32. data/lib/spark_engine/scaffold/gem/lib/gem.rb +12 -0
  33. data/lib/spark_engine/scaffold/gem/site/app/assets/javascripts/application.js +1 -0
  34. data/lib/spark_engine/scaffold/gem/site/app/assets/stylesheets/application.scss +2 -0
  35. data/lib/spark_engine/scaffold/gem/site/app/controllers/docs_controller.rb +19 -0
  36. data/lib/spark_engine/scaffold/gem/site/app/views/docs/index.html.erb +1 -0
  37. data/lib/spark_engine/scaffold/gem/site/app/views/layouts/application.html.erb +4 -0
  38. data/lib/spark_engine/scaffold/gem/site/config/application.rb +18 -0
  39. data/lib/spark_engine/scaffold/gem/site/config/environments/development.rb +13 -0
  40. data/lib/spark_engine/scaffold/gem/site/config/routes.rb +3 -0
  41. data/lib/spark_engine/scaffold.rb +191 -0
  42. data/lib/spark_engine/version.rb +3 -0
  43. data/lib/spark_engine.rb +106 -0
  44. data/spark_engine.gemspec +31 -0
  45. metadata +234 -0
@@ -0,0 +1,103 @@
1
+ require 'sass'
2
+ require 'yaml'
3
+
4
+ module SparkEngine
5
+ module SassParser
6
+ extend self
7
+
8
+ # Global vars beginning with underscore will have their children promoted to globals
9
+ # and will be assigned without the underscore
10
+ #
11
+ # For example: _colors: { yellow: '#fco' }
12
+ # becomes: colors: { yellow: '#fco'}, yellow: '#fco'
13
+ #
14
+ #
15
+ def load_yaml(data)
16
+ promote_globals YAML.load(data)
17
+ end
18
+
19
+ def read_file(file)
20
+ IO.read(file)
21
+ end
22
+
23
+ def promote_globals( data )
24
+ data.keys.select{|k| k.start_with?('_') }.each do |key|
25
+ data[key.sub(/^_/,'')] = data[key]
26
+ data = data.delete(key).merge(data)
27
+ end
28
+
29
+ data
30
+ end
31
+
32
+ def expand_vars(file)
33
+ content = read_file(file)
34
+ file_data = load_yaml(content)
35
+
36
+ content = content.gsub(/\$(?<var>\w+)/) do
37
+ file_data[$~[:var]].inspect
38
+ end
39
+
40
+ load_yaml content
41
+ end
42
+
43
+ def parse(file)
44
+ expand_vars file
45
+ end
46
+ end
47
+
48
+ class Importer < Sass::Importers::Filesystem
49
+
50
+ def watched_file?(uri)
51
+ !!(uri =~ /\.yml$/ &&
52
+ uri.start_with?(root + File::SEPARATOR))
53
+ end
54
+
55
+ protected
56
+
57
+ def extensions
58
+ {'yml' => :scss}
59
+ end
60
+
61
+ def yaml?(name)
62
+ File.extname(name) == '.yml'
63
+ end
64
+
65
+ private
66
+
67
+ def _find(dir, name, options)
68
+ return unless yaml? name
69
+
70
+ full_filename, syntax = Sass::Util.destructure(find_real_file(dir, name, options))
71
+ return unless full_filename && File.readable?(full_filename)
72
+
73
+ yaml = SassParser.parse(full_filename)
74
+ variables = yaml.map { |key, value| "$#{key}: #{_convert_to_sass(value)};" }.join("\n")
75
+
76
+ Sass::Engine.new(variables, options.merge(
77
+ :filename => full_filename,
78
+ :importer => self,
79
+ :syntax => :scss
80
+ ))
81
+ end
82
+
83
+ def _convert_to_sass(item)
84
+ if item.is_a? Array
85
+ _make_list(item)
86
+ elsif item.is_a? Hash
87
+ _make_map(item)
88
+ else
89
+ item.to_s
90
+ end
91
+ end
92
+
93
+ def _make_list(item)
94
+ '(' + item.map { |i| _convert_to_sass(i) }.join(',') + ')'
95
+ end
96
+
97
+ def _make_map(item)
98
+ '(' + item.map {|key, value| key.to_s + ':' + _convert_to_sass(value) }.join(',') + ')'
99
+ end
100
+ end
101
+
102
+ end
103
+
@@ -0,0 +1,18 @@
1
+ .DS_Store
2
+ .bundle/
3
+ .vscode/
4
+ .yardoc
5
+ _yardoc/
6
+ coverage/
7
+ doc/
8
+ /spec/reports/
9
+ /tmp/
10
+ log/*.log
11
+ pkg/
12
+ node_modules
13
+ site/tmp/
14
+ /public/
15
+ .sass-cache
16
+ .esvg-cache
17
+ _icons.js
18
+ _esvg.js
@@ -0,0 +1,3 @@
1
+ // Require modules, add code, etc
2
+
3
+ window.<%= @engine %> = module.exports = {}
@@ -0,0 +1 @@
1
+ // Design System Stylesheets index
@@ -0,0 +1,4 @@
1
+ module <%= @plugin_module %>
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title><%= @plugin_module %></title>
5
+ <%%= csrf_meta_tags %>
6
+ <%%= asset_tags %>
7
+ <%%= yield :stylesheets %>
8
+ <%%= yield :head %>
9
+ </head>
10
+
11
+ <body>
12
+ <div class='site'>
13
+ <div class='page'><%%= yield %></div>
14
+ </div>
15
+ </body>
16
+ <%%= javascript_tag "<%= @engine %>" %>
17
+ <%%= yield :javascripts %>
18
+ </html>
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ require "<%= @spec.name %>/version"
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "<%= @spec.name %>"
9
+ spec.version = <%= @gem_module %>::VERSION
10
+ spec.authors = <%= @spec.authors %>
11
+ spec.email = <%= @spec.email %>
12
+ spec.summary = "Summary of your gem."
13
+ spec.description = "Description of your gem (usually longer)."
14
+ spec.license = "<%= @spec.license %>"
15
+
16
+ spec.files = Dir["{app,lib,public,config}/**/*", "LICENSE.txt", "README.md"]
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_dependency "rails", ">= 4"
20
+ spec.add_runtime_dependency "spark_engine"
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.12"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ end
@@ -0,0 +1,12 @@
1
+ require 'spark_engine'
2
+ require '<%= @gem %>/version'
3
+
4
+ module <%= @gem_module %>
5
+ class Plugin < SparkEngine::Plugin
6
+ end
7
+ end
8
+
9
+ SparkEngine.register(<%= @gem_module %>::Plugin, {
10
+ gem: '<%= @gem %>'<% unless @engine.nil? %>,
11
+ engine: '<%= @engine %>'<% end %>
12
+ })
@@ -0,0 +1,2 @@
1
+ /* *= require_self */
2
+ @import '<%= @engine %>/index';
@@ -0,0 +1,19 @@
1
+ class DocsController < ApplicationController
2
+ def show
3
+ page = params[:page]
4
+
5
+ %w(docs).each do | root_page |
6
+ if page.match(/#{root_page}\/?$/)
7
+ page = File.join(root_page, 'index')
8
+ end
9
+ end
10
+
11
+ if template_exists? page
12
+ render template: page
13
+ elsif template_exists? "docs/\#{page}"
14
+ render template: "docs/\#{page}"
15
+ else
16
+ render file: "404.html", status: :not_found
17
+ end
18
+ end
19
+ end
@@ -0,0 +1 @@
1
+ <h1><%= @plugin_module %> Documentation</h1>
@@ -0,0 +1,4 @@
1
+ <%%= render_layout '<%= namespace %>/default' do %>
2
+ <%%= stylesheets { stylesheet_link_tag('application') } %>
3
+ <%%= javascripts { javascript_include_tag('application') } %>
4
+ <%% end %>
@@ -0,0 +1,18 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "rails"
4
+ # Pick the frameworks you want:
5
+ require "action_controller/railtie"
6
+ require "action_view/railtie"
7
+ require "sprockets/railtie"
8
+
9
+ # Require the gems listed in Gemfile, including any gems
10
+ # you've limited to :test, :development, or :production.
11
+ Bundler.require(*Rails.groups)
12
+
13
+ require '<%= @gem %>'
14
+
15
+ module Site
16
+ class Application < SparkEngine::Application
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ Rails.application.configure do
2
+ config.cache_classes = false
3
+
4
+ # Do not eager load code on boot.
5
+ config.eager_load = false
6
+
7
+ # Show full error reports and disable caching.
8
+ config.consider_all_requests_local = true
9
+ config.action_controller.perform_caching = false
10
+
11
+ # Print deprecation notices to the Rails logger.
12
+ config.active_support.deprecation = :log
13
+ end
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ resources :docs, param: :page, path: ''
3
+ end
@@ -0,0 +1,191 @@
1
+ require 'fileutils'
2
+ require "spark_engine/command/npm"
3
+
4
+ module SparkEngine
5
+ class Scaffold
6
+ attr_reader :gem, :engine, :namespace, :plugin_module, :path, :gemspec_path
7
+
8
+ def initialize(options)
9
+ @cwd = File.expand_path(File.dirname(options[:name]))
10
+ @gem = underscorize(File.basename(options[:name]))
11
+ @engine = underscorize(options[:engine] || @gem)
12
+ @namespace = @engine
13
+ @plugin_module = modulize @engine
14
+ @gem_module = modulize @gem
15
+ @gem_temp = ".#{@gem}-temp"
16
+
17
+ FileUtils.mkdir_p @cwd
18
+
19
+ Dir.chdir @cwd do
20
+ puts "Creating new plugin #{@namespace}".bold
21
+
22
+ @gemspec_path = new_gem
23
+ @spec = Gem::Specification.load(@gemspec_path)
24
+ @path = File.expand_path(File.dirname(@gemspec_path))
25
+
26
+ engine_scaffold
27
+
28
+ bootstrap_gem
29
+ setup_package_json
30
+ update_git
31
+ end
32
+
33
+ post_install
34
+ end
35
+
36
+ # Create a new gem with Bundle's gem command
37
+ #
38
+ def new_gem
39
+ system "bundler gem #{gem}"
40
+ Dir.glob(File.join(gem, "/*.gemspec")).first
41
+ end
42
+
43
+ def setup_package_json
44
+ Dir.chdir path do
45
+ NPM.setup
46
+ end
47
+ end
48
+
49
+ def bootstrap_gem
50
+
51
+ # Remove bin
52
+ FileUtils.rm_rf(File.join(path, 'bin'))
53
+
54
+ scaffold_path = File.expand_path("scaffold/**/*", File.dirname(__FILE__))
55
+
56
+ Dir.glob(scaffold_path, File::FNM_DOTMATCH).select{|f| File.file? f}.each do |f|
57
+ write_template f.split(/spark_engine\/scaffold\//)[1]
58
+ end
59
+ end
60
+
61
+ # Create an Rails plugin engine for documentation site
62
+ def engine_scaffold
63
+ FileUtils.mkdir_p(@gem_temp)
64
+ Dir.chdir(@gem_temp) do
65
+ response = Open3.capture3("rails plugin new #{gem} --mountable --dummy-path=site --skip-test-unit")
66
+ if !response[1].empty?
67
+ puts response[1]
68
+ abort "FAILED: Please be sure you have the rails gem installed with `gem install rails`"
69
+ end
70
+
71
+ # Remove files and directories that are unnecessary for the
72
+ # light-weight Rails documentation site
73
+ remove = %w(mailers models assets channels jobs views).map{ |f| File.join('app', f) }
74
+ remove.concat %w(cable.yml storage.yml database.yml).map{ |f| File.join('config', f) }
75
+
76
+ remove.each { |f| FileUtils.rm_rf File.join(@gem, 'site', f), secure: true }
77
+ end
78
+
79
+
80
+ engine_copy
81
+ end
82
+
83
+ # Copy parts of the engine scaffold into site directory
84
+ def engine_copy
85
+ site_path = File.join path, 'site'
86
+ FileUtils.mkdir_p site_path
87
+
88
+ ## Copy Rails plugin files
89
+ Dir.chdir "#{@gem_temp}/#{gem}/site" do
90
+ %w(app config bin config.ru Rakefile public log).each do |item|
91
+ target = File.join site_path, item
92
+
93
+ FileUtils.cp_r item, target
94
+
95
+ action_log "create", target.sub(@cwd+'/','')
96
+ end
97
+
98
+ end
99
+
100
+ # Remove temp dir
101
+ FileUtils.rm_rf @gem_temp
102
+ end
103
+
104
+ def update_git
105
+ Dir.chdir gem do
106
+ system "git reset"
107
+ system "git add -A"
108
+ end
109
+ end
110
+
111
+ def write_template(template, target=nil)
112
+ template_path = File.expand_path("scaffold/#{template}", File.dirname(__FILE__))
113
+
114
+ # Extract file extension
115
+ ext = File.extname(template)
116
+
117
+ # Replace keywords with correct names (excluding file extensions)
118
+ target_path = template.sub(/#{ext}$/, '').gsub(/(gem|engine|namespace)/, {
119
+ 'gem' => @gem,
120
+ 'engine' => @engine,
121
+ 'namespace' => @namespace
122
+ }) + ext
123
+
124
+ write_file target_path, read_template(template_path)
125
+ end
126
+
127
+ def read_template(file_path)
128
+ contents = ''
129
+ File.open file_path do |f|
130
+ contents = ERB.new(f.read).result(binding)
131
+ end
132
+ contents
133
+ end
134
+
135
+ def write_file(paths, content='', mode='w')
136
+ paths = [paths].flatten
137
+ paths.each do |path|
138
+ if File.exist?(path)
139
+ type = 'update'
140
+ else
141
+ FileUtils.mkdir_p(File.dirname(path))
142
+ type = 'create'
143
+ end
144
+
145
+ File.open path, mode do |io|
146
+ io.write(content)
147
+ end
148
+
149
+ action_log(type, path)
150
+ end
151
+ end
152
+
153
+ def post_install
154
+ require 'pathname'
155
+
156
+ target = Pathname.new File.join(@cwd, @gem)
157
+ dir = target.relative_path_from Pathname.new(Dir.pwd)
158
+ victory = "#{@plugin_module} Design System created at #{dir}. Huzzah!"
159
+ dashes = ''
160
+ victory.size.times{ dashes += '-' }
161
+
162
+ puts "\n#{victory}\n#{dashes}".bold
163
+
164
+ puts "Install dependencies:"
165
+ puts " - cd #{dir}"
166
+ puts " - bundle"
167
+ puts " - yarn install (or npm install)\n\n"
168
+ puts "Then give it a spin.\n\n"
169
+ puts " spark build".bold + " - builds assets"
170
+ puts " spark server".bold + " - view documentation site in a server"
171
+ puts " spark help".bold + " - learn more…"
172
+ puts dashes + "\n\n"
173
+ end
174
+
175
+ def action_log(action, path)
176
+ puts action.rjust(12).colorize(:green).bold + " #{path}"
177
+ end
178
+
179
+ def modulize(input)
180
+ input.split('_').collect { |name|
181
+ (name =~ /[A-Z]/) ? name : name.capitalize
182
+ }.join
183
+ end
184
+
185
+ def underscorize(input)
186
+ input.gsub(/[A-Z]/) do |char|
187
+ '_'+char
188
+ end.sub(/^_/,'').downcase
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,3 @@
1
+ module SparkEngine
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,106 @@
1
+ require "open3"
2
+ require "json"
3
+ require "colorize"
4
+
5
+ require "spark_engine/version"
6
+ require "spark_engine/plugin"
7
+ require "spark_engine/assets"
8
+ require "spark_engine/sass/engine"
9
+ require "spark_engine/sass/importer"
10
+ require "spark_engine/config_data"
11
+
12
+ module SparkEngine
13
+ extend self
14
+ attr_accessor :plugin
15
+ autoload :Application, "spark_engine/middleware"
16
+
17
+ def production?
18
+ ENV['CI'] || ENV['RAILS_ENV'] == 'production' || ( defined?(Command) && Command.production? )
19
+ end
20
+
21
+ def rails5?
22
+ Gem::Version.new(Rails.version) >= Gem::Version.new('5')
23
+ end
24
+
25
+ def plugin
26
+ @plugin
27
+ end
28
+
29
+ def config_data
30
+ SparkEngine::ConfigData.read(SparkEngine.plugin.root, Rails.root)
31
+ end
32
+
33
+ def register(plugin_module, options={}, &block)
34
+ @plugin = plugin_module.new(options)
35
+ if defined? Rails
36
+ @plugin.create_engine(&block)
37
+ patch_rails
38
+ end
39
+ end
40
+
41
+ def patch_rails
42
+ load_helpers
43
+ end
44
+
45
+ def load_helpers
46
+ require "spark_engine/helpers/asset_helpers"
47
+ require "spark_engine/helpers/layout_helpers"
48
+
49
+ SparkEngine::Helpers.constants.each do |c|
50
+ helper = SparkEngine::Helpers.const_get(c)
51
+ ActionView::Base.send :include, helper if defined? ActionView::Base
52
+ end
53
+ end
54
+
55
+ def at_rails_root?
56
+ File.exist?("bin/rails")
57
+ end
58
+
59
+ def plugin_gemspec
60
+ if gem_path
61
+ path = File.join(gem_path, "*.gemspec")
62
+ Dir[path].first
63
+ end
64
+ end
65
+
66
+ def plugin_spec
67
+ @plugin_spec ||= begin
68
+ if file = plugin_gemspec
69
+ spec = Gem::Specification.load(file)
70
+ spec if spec.name != 'spark_engine'
71
+ end
72
+ end
73
+ end
74
+
75
+ def load_plugin
76
+ plugin || if spec = plugin_spec
77
+ require spec.name unless spec.name == 'spark_engine'
78
+ return plugin
79
+ end
80
+ end
81
+
82
+ def at_gem_root?
83
+ !Dir['*.gemspec'].empty?
84
+ end
85
+
86
+ def gem_path
87
+ if at_gem_root?
88
+ Dir.pwd
89
+ elsif at_rails_root?
90
+ "../"
91
+ end
92
+ end
93
+
94
+ def rails_path(sub=nil)
95
+ path = if at_rails_root?
96
+ Dir.pwd
97
+ else
98
+ dir = Dir["**/bin/rails"]
99
+ if !dir.empty?
100
+ dir.first.split('/').first
101
+ end
102
+ end
103
+ path = File.join(path, sub) if sub
104
+ path
105
+ end
106
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'spark_engine/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'spark_engine'
7
+ spec.version = SparkEngine::VERSION
8
+ spec.authors = ['Brandon Mathis']
9
+ spec.email = ['brandon@imathis.com']
10
+
11
+ spec.summary = %q{A design system framework for Rails (and humans).}
12
+ spec.homepage = 'https://github.com/imathis/spark'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.bindir = 'bin'
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_runtime_dependency 'sass', '~> 3.4'
21
+ spec.add_runtime_dependency 'esvg', '~> 4.2'
22
+ spec.add_runtime_dependency 'listen', '~> 3.0.0'
23
+ spec.add_runtime_dependency 'block_helpers', '~> 0.3'
24
+ spec.add_runtime_dependency 'colorize', '~> 0.8'
25
+ spec.add_runtime_dependency 'bundler', '~> 1.10'
26
+ spec.add_runtime_dependency 'autoprefixer-rails', '~> 9.0'
27
+ spec.add_runtime_dependency 'rails', '>= 4.2', '< 6'
28
+
29
+ spec.add_development_dependency 'rake', '~> 10.0'
30
+ spec.add_development_dependency 'pry-byebug'
31
+ end