maglove 0.8.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +157 -0
  4. data/Gemfile.lock +59 -49
  5. data/bin/maglove +13 -13
  6. data/data/maglove/export.haml +11 -0
  7. data/data/maglove/index.haml +17 -0
  8. data/data/maglove/maglove.css +62 -0
  9. data/data/maglove/maglove.haml +18 -0
  10. data/data/maglove/maglove.js +68 -0
  11. data/lib/block_resolver.rb +6 -0
  12. data/lib/ext/thor/option.rb +43 -0
  13. data/lib/magloft/api.rb +39 -0
  14. data/lib/magloft/api_caller.rb +67 -0
  15. data/lib/magloft/remote_collection.rb +50 -0
  16. data/lib/magloft/remote_resource.rb +124 -0
  17. data/lib/magloft/transformable.rb +11 -0
  18. data/lib/magloft/typeloft_block.rb +18 -0
  19. data/lib/magloft/typeloft_image.rb +18 -0
  20. data/lib/magloft/typeloft_template.rb +18 -0
  21. data/lib/magloft/typeloft_theme.rb +41 -0
  22. data/lib/magloft.rb +3 -0
  23. data/lib/maglove/application.rb +10 -12
  24. data/lib/maglove/asset/theme.rb +37 -32
  25. data/lib/maglove/commands/assets.rb +85 -0
  26. data/lib/maglove/commands/base.rb +55 -0
  27. data/lib/maglove/commands/fonts.rb +69 -0
  28. data/lib/maglove/commands/main.rb +24 -0
  29. data/lib/maglove/commands/theme.rb +197 -0
  30. data/lib/maglove/helper/log_helper.rb +3 -18
  31. data/lib/maglove/middleware/live_reload.rb +97 -0
  32. data/lib/maglove/phantom_script.rb +9 -10
  33. data/lib/maglove/server.rb +46 -78
  34. data/lib/maglove/tilt/coffee_template.rb +7 -6
  35. data/lib/maglove/tilt/haml_template.rb +4 -4
  36. data/lib/maglove/tilt/js_template.rb +8 -8
  37. data/lib/maglove/tilt/less_template.rb +5 -4
  38. data/lib/maglove/tilt/scss_template.rb +17 -11
  39. data/lib/maglove/tilt/yaml_template.rb +3 -2
  40. data/lib/maglove/version.rb +1 -1
  41. data/lib/maglove/workspace.rb +41 -0
  42. data/lib/maglove.rb +38 -49
  43. data/lib/powersnap.rb +24 -0
  44. data/lib/workspace/workspace_dir/archive.rb +18 -0
  45. data/lib/workspace/workspace_dir.rb +98 -0
  46. data/lib/workspace/workspace_file/archive.rb +45 -0
  47. data/lib/workspace/workspace_file/media.rb +19 -0
  48. data/lib/workspace/workspace_file/net.rb +18 -0
  49. data/lib/workspace/workspace_file/parse.rb +21 -0
  50. data/lib/workspace/workspace_file.rb +99 -0
  51. data/lib/workspace.rb +11 -0
  52. data/maglove.gemspec +12 -12
  53. metadata +100 -86
  54. data/data/maglove/dump.haml +0 -58
  55. data/data/maglove/sdk.haml +0 -27
  56. data/lib/ext/commander/command.rb +0 -32
  57. data/lib/ext/commander/methods.rb +0 -8
  58. data/lib/maglove/asset/base_theme.rb +0 -17
  59. data/lib/maglove/command/compile.rb +0 -44
  60. data/lib/maglove/command/compress.rb +0 -28
  61. data/lib/maglove/command/copy.rb +0 -35
  62. data/lib/maglove/command/core.rb +0 -23
  63. data/lib/maglove/command/font.rb +0 -80
  64. data/lib/maglove/command/server.rb +0 -16
  65. data/lib/maglove/command/sync.rb +0 -17
  66. data/lib/maglove/command/theme.rb +0 -175
  67. data/lib/maglove/command/util.rb +0 -45
  68. data/lib/maglove/helper/asset_helper.rb +0 -24
  69. data/lib/maglove/helper/command_helper.rb +0 -67
  70. data/lib/maglove/helper/theme_helper.rb +0 -105
  71. data/lib/maglove/server/hpub.rb +0 -185
  72. data/lib/maglove/template/tumblr.rb +0 -81
  73. data/lib/maglove/tilt/twig_template.rb +0 -49
@@ -0,0 +1,67 @@
1
+ module MagLoft
2
+ class ApiCaller < Dialers::Caller
3
+ MAX_RETRIES = 0
4
+ TIMEOUT_IN_SECONDS = 600
5
+ MAGLOFT_API_URL = "https://www.magloft.dev"
6
+ MAGLOFT_CDN_URL = "https://cdn.magloft.dev/"
7
+
8
+ setup_api(url: MAGLOFT_API_URL) do |faraday|
9
+ faraday.request :json
10
+ faraday.request :request_headers, accept: "application/json"
11
+ faraday.response :json
12
+ faraday.adapter :net_http
13
+ faraday.options.timeout = TIMEOUT_IN_SECONDS
14
+ faraday.options.open_timeout = TIMEOUT_IN_SECONDS
15
+ faraday.ssl.verify = false
16
+ end
17
+
18
+ def http_call(request_options, current_retries = 0)
19
+ request_options.headers["X-Magloft-Accesstoken"] = Api.client.token
20
+ super
21
+ end
22
+
23
+ def transform(response)
24
+ self.class.short_circuits.search_for_stops(response)
25
+ Transformable.new(response)
26
+ end
27
+
28
+ short_circuits.add(
29
+ if: -> (response) { Dialers::Status.new(response.status).server_error? },
30
+ do: -> (response) { fail Dialers::ServerError, response }
31
+ )
32
+
33
+ short_circuits.add(
34
+ if: -> (response) { Dialers::Status.new(response.status).is?(404) },
35
+ do: -> (response) { fail Dialers::NotFoundError, response }
36
+ )
37
+
38
+ short_circuits.add(
39
+ if: -> (response) { Dialers::Status.new(response.status).is?(409) },
40
+ do: -> (response) { fail ConflictError, response }
41
+ )
42
+
43
+ short_circuits.add(
44
+ if: -> (response) { Dialers::Status.new(response.status).is?(400) },
45
+ do: -> (response) { fail ValidationError, response }
46
+ )
47
+
48
+ short_circuits.add(
49
+ if: -> (response) { Dialers::Status.new(response.status).is?(422) },
50
+ do: -> (response) { fail ValidationError, response }
51
+ )
52
+
53
+ short_circuits.add(
54
+ if: -> (response) { Dialers::Status.new(response.status).is?(401) },
55
+ do: -> (response) { fail UnauthorizedError, response }
56
+ )
57
+
58
+ class ConflictError < Dialers::ErrorWithResponse
59
+ end
60
+
61
+ class ValidationError < Dialers::ErrorWithResponse
62
+ end
63
+
64
+ class UnauthorizedError < Dialers::ErrorWithResponse
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,50 @@
1
+ module MagLoft
2
+ class RemoteCollection
3
+ def initialize(resource_class, filter = {})
4
+ @resource_class = resource_class
5
+ @filter = filter
6
+ end
7
+
8
+ def new(attributes)
9
+ @resource_class.new(attributes.merge(@filter))
10
+ end
11
+
12
+ def find(id)
13
+ @resource_class.where(@filter.merge(id: id)).first
14
+ end
15
+
16
+ def where(params)
17
+ @resource_class.where(params.merge(@filter))
18
+ end
19
+
20
+ def find_one(params)
21
+ @resource_class.find_one(params.merge(@filter))
22
+ end
23
+
24
+ def all
25
+ @resource_class.where(@filter)
26
+ end
27
+
28
+ def method_missing(name, *args, &block)
29
+ if name[0..7] == "find_by_" and args.length == 1
30
+ attribute = name[8..-1].to_sym
31
+ if @resource_class.remote_attributes.include?(attribute)
32
+ params = {}
33
+ params[attribute] = args.first
34
+ return self.find_one(params.merge(@filter))
35
+ end
36
+ end
37
+ super
38
+ end
39
+
40
+ def respond_to_missing?(method_name, include_private = false)
41
+ method_name.to_s.start_with?('find_by_') || super
42
+ end
43
+
44
+ def create(attributes = {})
45
+ entity = @resource_class.new(attributes.merge(@filter))
46
+ entity.save
47
+ entity
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,124 @@
1
+ module MagLoft
2
+ class RemoteResource
3
+ attr_accessor :changed_data, :id
4
+ attr_reader :destroyed
5
+
6
+ def initialize(attributes = {})
7
+ allowed_attributes = attributes.slice(*self.class.remote_attributes)
8
+ Dialers::AssignAttributes.call(self, allowed_attributes.without(:id))
9
+ end
10
+
11
+ def changed?
12
+ self.changed_data.keys.count > 0
13
+ end
14
+
15
+ def destroyed?
16
+ self.destroyed == true
17
+ end
18
+
19
+ def save
20
+ return false if destroyed? or !changed?
21
+ if self.changed_data.keys.count > 0
22
+ if self.id.nil?
23
+ transformable = Api.client.api_caller.post(self.class.endpoint, self.changed_data)
24
+ else
25
+ transformable = Api.client.api_caller.put("#{self.class.endpoint}/#{self.id}", self.changed_data.without(:id))
26
+ end
27
+ transformable.transform_to_existing(self)
28
+ self.clear_changed_data!
29
+ end
30
+ self
31
+ end
32
+
33
+ def destroy
34
+ return false if self.id.nil? or self.destroyed?
35
+ transformable = Api.client.api_caller.delete("#{self.class.endpoint}/#{self.id}")
36
+ transformable.transform_to_existing(self)
37
+ @destroyed = true
38
+ self.clear_changed_data!
39
+ self
40
+ end
41
+
42
+ def changed_data
43
+ @changed_data ||= {}
44
+ end
45
+
46
+ def clear_changed_data!
47
+ self.changed_data = {}
48
+ self
49
+ end
50
+
51
+ def update_data(key, value)
52
+ if self.send(key) != value
53
+ instance_variable_set("@#{key}", value)
54
+ changed_data[key] = value
55
+ end
56
+ end
57
+
58
+ class << self
59
+ def remote_attributes
60
+ @remote_attributes ||= []
61
+ end
62
+
63
+ def remote_attribute(*args)
64
+ args.each do |arg|
65
+ remote_attributes.push(arg)
66
+ self.class_eval("attr_accessor :#{arg}")
67
+ self.class_eval("def #{arg}=(val);update_data(:#{arg}, val);end")
68
+ end
69
+ end
70
+
71
+ def endpoint(path = nil)
72
+ if path.nil?
73
+ @endpoint
74
+ else
75
+ @endpoint = path
76
+ end
77
+ end
78
+
79
+ def find(id)
80
+ api.get("#{endpoint}/#{id}").transform_to_one(self)
81
+ end
82
+
83
+ def find_one(params)
84
+ where(params).first
85
+ end
86
+
87
+ def where(params)
88
+ api.get(endpoint, params).transform_to_many(self)
89
+ end
90
+
91
+ def all
92
+ api.get(endpoint).transform_to_many(self)
93
+ end
94
+
95
+ def create(attributes = {})
96
+ entity = self.new(attributes)
97
+ entity.save
98
+ entity
99
+ end
100
+
101
+ def method_missing(name, *args, &block)
102
+ if name[0..7] == "find_by_" and args.length == 1
103
+ attribute = name[8..-1].to_sym
104
+ if remote_attributes.include?(attribute)
105
+ params = {}
106
+ params[attribute] = args.first
107
+ return self.find_one(params)
108
+ end
109
+ end
110
+ super
111
+ end
112
+
113
+ def respond_to_missing?(method_name, include_private = false)
114
+ method_name.to_s.start_with?('find_by_') || super
115
+ end
116
+
117
+ private
118
+
119
+ def api
120
+ Api.client.api_caller
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,11 @@
1
+ module MagLoft
2
+ class Transformable < Dialers::Transformable
3
+ def transform_attributes_to_object(entity_class_or_decider, attributes)
4
+ super.clear_changed_data!
5
+ end
6
+
7
+ def transform_to_existing(entity)
8
+ Dialers::AssignAttributes.call(entity, raw_data)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ module MagLoft
2
+ class TypeloftBlock < RemoteResource
3
+ endpoint "api/maglove/v1/typeloft_blocks"
4
+ remote_attribute :identifier, :name, :contents, :typeloft_theme_id, :user_id, :created_at, :updated_at
5
+ attr_accessor :thumbnail_policy
6
+
7
+ def upload_thumbnail(file_path)
8
+ return false if thumbnail_policy.nil?
9
+ conn = Faraday.new(url: thumbnail_policy["url"]) do |f|
10
+ f.ssl.verify = false
11
+ f.headers = thumbnail_policy["headers"]
12
+ f.adapter :net_http
13
+ end
14
+ response = conn.put(nil, File.read(file_path))
15
+ return (response.status == 200)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module MagLoft
2
+ class TypeloftImage < RemoteResource
3
+ endpoint "api/maglove/v1/typeloft_images"
4
+ remote_attribute :title, :user_id, :typeloft_folder_id, :typeloft_theme_id, :remote_file, :md5
5
+ attr_accessor :policy, :content_type
6
+
7
+ def upload(file_path)
8
+ return false if policy.nil?
9
+ conn = Faraday.new(url: policy["url"]) do |f|
10
+ f.ssl.verify = false
11
+ f.headers = policy["headers"]
12
+ f.adapter :net_http
13
+ end
14
+ response = conn.put(nil, File.read(file_path))
15
+ return (response.status == 200)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module MagLoft
2
+ class TypeloftTemplate < RemoteResource
3
+ endpoint "api/maglove/v1/typeloft_templates"
4
+ remote_attribute :identifier, :title, :contents, :public, :position, :typeloft_theme_id, :user_id, :created_at, :updated_at
5
+ attr_accessor :thumbnail_policy
6
+
7
+ def upload_thumbnail(file_path)
8
+ return false if thumbnail_policy.nil?
9
+ conn = Faraday.new(url: thumbnail_policy["url"]) do |f|
10
+ f.ssl.verify = false
11
+ f.headers = thumbnail_policy["headers"]
12
+ f.adapter :net_http
13
+ end
14
+ response = conn.put(nil, File.read(file_path))
15
+ return (response.status == 200)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,41 @@
1
+ module MagLoft
2
+ class TypeloftTheme < RemoteResource
3
+ endpoint "api/maglove/v1/typeloft_themes"
4
+ remote_attribute :identifier, :name, :description, :base_version, :widgets, :fonts, :user_id, :screenshots, :active
5
+ attr_accessor :stylesheet_policy, :javascript_policy
6
+
7
+ def typeloft_templates
8
+ RemoteCollection.new(TypeloftTemplate, { typeloft_theme_id: self.id })
9
+ end
10
+
11
+ def typeloft_images
12
+ RemoteCollection.new(TypeloftImage, { typeloft_theme_id: self.id })
13
+ end
14
+
15
+ def typeloft_blocks
16
+ RemoteCollection.new(TypeloftBlock, { typeloft_theme_id: self.id })
17
+ end
18
+
19
+ def upload_javascript(file_path)
20
+ return false if javascript_policy.nil?
21
+ conn = Faraday.new(url: javascript_policy["url"]) do |f|
22
+ f.ssl.verify = false
23
+ f.headers = javascript_policy["headers"]
24
+ f.adapter :net_http
25
+ end
26
+ response = conn.put(nil, File.read(file_path))
27
+ return (response.status == 200)
28
+ end
29
+
30
+ def upload_stylesheet(file_path)
31
+ return false if stylesheet_policy.nil?
32
+ conn = Faraday.new(url: stylesheet_policy["url"]) do |f|
33
+ f.ssl.verify = false
34
+ f.headers = stylesheet_policy["headers"]
35
+ f.adapter :net_http
36
+ end
37
+ response = conn.put(nil, File.read(file_path))
38
+ return (response.status == 200)
39
+ end
40
+ end
41
+ end
data/lib/magloft.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "magloft/api"
2
+ module MagLoft
3
+ end
@@ -1,7 +1,7 @@
1
1
  module MagLove
2
2
  class Application
3
3
  include Commander::Methods
4
-
4
+
5
5
  def run
6
6
  program :version, MagLove::VERSION
7
7
  program :description, 'MagLoft Themes Toolkit'
@@ -12,17 +12,16 @@ module MagLove
12
12
  logger.level = :debug
13
13
  end
14
14
  global_option '--verbosity LEVEL', 'Specify verbosity level (*info*, debug, warn, error)' do |verbosity|
15
- verbosity = "info" if !["info", "debug", "warn", "error"].include?(verbosity.to_s)
15
+ verbosity = "info" unless ["info", "debug", "warn", "error"].include?(verbosity.to_s)
16
16
  logger.level = verbosity.to_sym
17
17
  end
18
18
  widgets_path = "widgets"
19
19
  global_option '--widgets-path PATH', 'Specify path to custom widgets' do |path|
20
- error!("▸ Invalid widgets path: #{path}") if !File.directory?(path)
20
+ error!("▸ Invalid widgets path: #{path}") unless File.directory?(path)
21
21
  widgets_path = path
22
22
  end
23
- global_option '--production'
24
23
  default_command :help
25
-
24
+
26
25
  # Register Widgets
27
26
  if File.directory?(widgets_path)
28
27
  Dir["#{widgets_path}/**/*.rb"].each do |widget_path|
@@ -31,9 +30,9 @@ module MagLove
31
30
  Hamloft.register_widget(klass_name.constantize)
32
31
  end
33
32
  end
34
-
33
+
35
34
  logger.level = ENV["LOG_LEVEL"].to_sym if ENV["LOG_LEVEL"]
36
-
35
+
37
36
  MagLove::Command::Theme.new.run
38
37
  MagLove::Command::Core.new.run
39
38
  MagLove::Command::Compile.new.run
@@ -43,18 +42,17 @@ module MagLove
43
42
  MagLove::Command::Font.new.run
44
43
  MagLove::Command::Sync.new.run
45
44
  MagLove::Command::Server.new.run
46
-
45
+
47
46
  # allow colons
48
- ARGV[0] = ARGV[0].gsub(":", "-") if ARGV[0]
49
-
47
+ ARGV[0] = ARGV[0].tr(":", "-") if ARGV[0]
48
+
50
49
  # merge first two commands
51
50
  if ARGV.length > 1 and defined_commands.keys.include?("#{ARGV[0]}-#{ARGV[1]}")
52
51
  ARGV[0] = "#{ARGV[0]}-#{ARGV[1]}"
53
52
  ARGV.slice!(1)
54
53
  end
55
-
54
+
56
55
  run!
57
56
  end
58
-
59
57
  end
60
58
  end
@@ -1,42 +1,48 @@
1
+ require "tilt"
2
+ require "sass"
3
+ require "less"
4
+ require "maglove/tilt/haml_template"
5
+ require "maglove/tilt/less_template"
6
+ require "maglove/tilt/scss_template"
7
+ require "maglove/tilt/coffee_template"
8
+ require "maglove/tilt/js_template"
9
+ require "maglove/tilt/yaml_template"
10
+
1
11
  module MagLove
2
12
  module Asset
3
13
  class Theme
4
- include MagLove::Helper::AssetHelper
14
+ include Workspace
5
15
  include MagLove::Helper::LogHelper
6
- include MagLove::Helper::ThemeHelper
7
- attr_reader :mtime, :path, :theme, :valid, :locals, :contents
16
+ attr_reader :mtime, :path, :valid, :contents, :options
8
17
 
9
18
  OUTPUT_MAPPING = {
10
19
  "haml" => "html",
11
- "twig" => "html",
12
20
  "less" => "css",
13
21
  "scss" => "css",
14
22
  "coffee" => "js",
15
23
  "yml" => "json"
16
24
  }
17
25
 
18
- def initialize(path, theme, locals={})
26
+ def initialize(path, options = {})
19
27
  @path = path
20
- @theme = theme
21
- @locals = locals
28
+ @options = options
22
29
  @mtime = File.mtime(absolute_path)
23
30
  begin
24
31
  if ::Tilt[input_type]
25
32
  template = ::Tilt.new(absolute_path)
26
- locals[:base_path] = theme_base_path(nil, theme)
27
- @contents = template.render(Object.new, locals)
33
+ @contents = template.render(Object.new, @options.merge(base_path: theme_base_dir.to_s))
28
34
  else
29
35
  @contents = File.read(absolute_path)
30
36
  end
31
- rescue Exception => e
37
+ rescue StandardError => e
32
38
  error("▸ #{e.message}")
33
39
  end
34
40
  end
35
-
41
+
36
42
  def input_type
37
- File.extname(path).gsub("\.", "")
43
+ File.extname(path).delete("\.")
38
44
  end
39
-
45
+
40
46
  def output_type
41
47
  OUTPUT_MAPPING[input_type] or input_type
42
48
  end
@@ -48,41 +54,40 @@ module MagLove
48
54
  def write!
49
55
  write_to!(output_path)
50
56
  end
51
-
57
+
52
58
  def write_to!(path)
53
- return false if not valid?
59
+ return false unless valid?
54
60
  FileUtils.mkdir_p(File.dirname(path))
55
-
56
- File.open("#{path}+", 'wb') do |f|
57
- f.write @contents
58
- end
59
-
60
- # Atomic write
61
+ File.open("#{path}+", 'wb') { |f| f.write @contents }
61
62
  FileUtils.mv("#{path}+", path)
62
-
63
- # Set mtime correctly
64
63
  File.utime(mtime, mtime, path)
65
-
66
64
  true
67
65
  ensure
68
- # Ensure tmp file gets cleaned up
69
66
  FileUtils.rm("#{path}+") if File.exist?("#{path}+")
70
67
  end
71
-
68
+
72
69
  def absolute_path
73
- File.absolute_path("src/themes/#{theme}/#{path}")
70
+ if @options[:base]
71
+ File.absolute_path("src/base/#{theme_config(:base_version)}/#{path}")
72
+ else
73
+ File.absolute_path("src/themes/#{@options[:theme]}/#{path}")
74
+ end
74
75
  end
75
76
 
76
77
  def logical_path
77
- return false if not valid?
78
- "#{File.dirname(path)}/#{File.basename(path,'.*')}.#{output_type}"
78
+ return false unless valid?
79
+ dirname = File.dirname(path)
80
+ if dirname == "/"
81
+ "#{File.basename(path, '.*')}.#{output_type}"
82
+ else
83
+ "#{dirname}/#{File.basename(path, '.*')}.#{output_type}"
84
+ end
79
85
  end
80
86
 
81
87
  def output_path
82
- return false if not valid?
83
- "dist/themes/#{theme}/#{logical_path}"
88
+ return false unless valid?
89
+ "dist/themes/#{@options[:theme]}/#{logical_path}"
84
90
  end
85
-
86
91
  end
87
92
  end
88
93
  end
@@ -0,0 +1,85 @@
1
+ module MagLove
2
+ module Commands
3
+ class Assets < Base
4
+ class_option :theme, type: :string, required: true, validator: OptionValidator
5
+
6
+ desc "compile", "Compile all assets"
7
+ def compile
8
+ invoke(:clean)
9
+ invoke(:images)
10
+ invoke(:javascript)
11
+ invoke(:stylesheet)
12
+ invoke(:yaml)
13
+ invoke(:templates)
14
+ invoke(:blocks)
15
+ end
16
+
17
+ desc "clean", "Clean theme dist directory"
18
+ def clean
19
+ info("▸ Cleaning up Theme Directory")
20
+ theme_dir(root: "dist").reset!
21
+ end
22
+
23
+ desc "images", "Copy images"
24
+ def images
25
+ info("▸ Copying Images")
26
+ workspace_dir("src/base/#{theme_config(:base_version)}").files("images/**/*.{jpg,png,gif,svg}").each do |file|
27
+ debug("~> Copying #{file}")
28
+ file.asset(theme: options.theme, base: true).write!
29
+ end
30
+ theme_dir.files("images/**/*.{jpg,png,gif,svg}").each do |file|
31
+ debug("~> Copying #{file}")
32
+ file.asset.write!
33
+ end
34
+ end
35
+
36
+ desc "javascript", "Compile JavaScript"
37
+ def javascript
38
+ info("▸ Compiling JavaScript")
39
+ theme_dir.file("theme.coffee").asset.write!
40
+ end
41
+
42
+ desc "stylesheet", "Compile Stylesheet"
43
+ def stylesheet
44
+ info("▸ Compiling Stylesheet")
45
+ theme_dir.files("theme.{scss,less}").first.asset.write!
46
+ end
47
+
48
+ desc "yaml", "Compile YAML Manifest"
49
+ def yaml
50
+ info("▸ Compiling YAML Manifest")
51
+ theme_dir.file("theme.yml").asset.write!
52
+ end
53
+
54
+ desc "templates", "Compile HAML Templates"
55
+ def templates
56
+ info("▸ Compiling HAML Templates")
57
+ asset_uri = "file://#{workspace_dir('dist').absolute_path}"
58
+ theme_config(:templates).each do |template|
59
+ debug "~> processing template #{template}"
60
+ template_file = theme_dir.file("templates/#{template}.haml")
61
+ error!("~> Template '#{template}' does not exist!") if template_file.nil?
62
+ contents = template_file.asset(asset_uri: asset_uri).contents
63
+ html_contents = gem_dir.file("export.haml").read_hamloft(theme: options.theme, contents: contents, asset_uri: asset_uri)
64
+ theme_dir(root: "dist").file("templates/#{template}.html").write(html_contents)
65
+ end
66
+ end
67
+
68
+ desc "blocks", "Compile HAML Blocks"
69
+ def blocks
70
+ info("▸ Compiling HAML Blocks")
71
+ if theme_dir.dir("blocks").exists?
72
+ asset_uri = "file://#{workspace_dir('dist').absolute_path}"
73
+ theme_dir.dir("blocks").files("**/*.haml").each do |block_file|
74
+ debug "~> processing block #{block_file.basename}"
75
+ contents = block_file.asset(asset_uri: asset_uri).contents
76
+ html_contents = gem_dir.file("export.haml").read_hamloft(theme: options.theme, contents: contents, asset_uri: asset_uri)
77
+ theme_dir(root: "dist").file("blocks/#{block_file.basename}.html").write(html_contents)
78
+ end
79
+ else
80
+ debug "~> no blocks available"
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,55 @@
1
+ require "maglove/helper/log_helper"
2
+ require "maglove/asset/theme"
3
+ module MagLove
4
+ module Commands
5
+ class Base < Thor
6
+ include MagLove::Helper::LogHelper
7
+ include Workspace
8
+
9
+ def initialize(args, opts, config)
10
+ namespace = self.class.name.split("::").last.underscore
11
+ command = config[:current_command].name
12
+ Logging.mdc["full_command"] = "#{namespace}:#{command}"
13
+ super
14
+ end
15
+
16
+ private
17
+
18
+ def magloft_api
19
+ @magloft_api ||= MagLoft::Api.client(options[:token])
20
+ end
21
+
22
+ def reset_invocations(*commands)
23
+ reset_command_invocations(self.class, *commands)
24
+ end
25
+
26
+ def reset_command_invocations(parent, *commands)
27
+ if commands.length.zero?
28
+ @_invocations[parent] = []
29
+ else
30
+ commands.each do |command|
31
+ @_invocations[parent].delete(command.to_s)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ module OptionValidator
38
+ def self.validate(switch, value)
39
+ case switch
40
+ when "--theme"
41
+ File.directory?("src/themes/#{value}")
42
+ else
43
+ true
44
+ end
45
+ end
46
+
47
+ def self.message(switch, value)
48
+ case switch
49
+ when "--theme"
50
+ "The theme '#{value}' does not exist!"
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end