maglove 0.3.0

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 (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/Gemfile +3 -0
  4. data/Gemfile.lock +137 -0
  5. data/README.md +26 -0
  6. data/bin/maglove +21 -0
  7. data/data/maglove/scaffold/base/base.coffee +1 -0
  8. data/data/maglove/scaffold/base/base.less +26 -0
  9. data/data/maglove/scaffold/base/images/base/loading-bars.svg +17 -0
  10. data/data/maglove/scaffold/base/less/base/animations.less +301 -0
  11. data/data/maglove/scaffold/base/less/base/blockquotes.less +23 -0
  12. data/data/maglove/scaffold/base/less/base/buttons.less +76 -0
  13. data/data/maglove/scaffold/base/less/base/code.less +19 -0
  14. data/data/maglove/scaffold/base/less/base/forms.less +115 -0
  15. data/data/maglove/scaffold/base/less/base/global.less +142 -0
  16. data/data/maglove/scaffold/base/less/base/grid-minimal.less +146 -0
  17. data/data/maglove/scaffold/base/less/base/grid-non-responsive.less +63 -0
  18. data/data/maglove/scaffold/base/less/base/grid.less +267 -0
  19. data/data/maglove/scaffold/base/less/base/helpers.less +146 -0
  20. data/data/maglove/scaffold/base/less/base/images.less +8 -0
  21. data/data/maglove/scaffold/base/less/base/lists.less +23 -0
  22. data/data/maglove/scaffold/base/less/base/mixins.less +107 -0
  23. data/data/maglove/scaffold/base/less/base/print.less +35 -0
  24. data/data/maglove/scaffold/base/less/base/resets.less +27 -0
  25. data/data/maglove/scaffold/base/less/base/tables.less +29 -0
  26. data/data/maglove/scaffold/base/less/core/alignments.less +17 -0
  27. data/data/maglove/scaffold/base/less/core/cleanup.less +8 -0
  28. data/data/maglove/scaffold/base/less/core/editor.less +23 -0
  29. data/data/maglove/scaffold/base/less/core/typography.less +74 -0
  30. data/data/maglove/scaffold/base/less/vendor/flex-video.less +22 -0
  31. data/data/maglove/scaffold/base/less/vendor/font-awesome/animated.less +34 -0
  32. data/data/maglove/scaffold/base/less/vendor/font-awesome/bordered-pulled.less +16 -0
  33. data/data/maglove/scaffold/base/less/vendor/font-awesome/core.less +13 -0
  34. data/data/maglove/scaffold/base/less/vendor/font-awesome/fixed-width.less +6 -0
  35. data/data/maglove/scaffold/base/less/vendor/font-awesome/font-awesome.less +17 -0
  36. data/data/maglove/scaffold/base/less/vendor/font-awesome/icons.less +596 -0
  37. data/data/maglove/scaffold/base/less/vendor/font-awesome/larger.less +13 -0
  38. data/data/maglove/scaffold/base/less/vendor/font-awesome/list.less +19 -0
  39. data/data/maglove/scaffold/base/less/vendor/font-awesome/mixins.less +27 -0
  40. data/data/maglove/scaffold/base/less/vendor/font-awesome/rotated-flipped.less +20 -0
  41. data/data/maglove/scaffold/base/less/vendor/font-awesome/stacked.less +20 -0
  42. data/data/maglove/scaffold/base/less/vendor/font-awesome/variables.less +606 -0
  43. data/data/maglove/scaffold/base/less/vendor/font-awesome.less +16 -0
  44. data/data/maglove/scaffold/base/less/vendor/image-loader.less +15 -0
  45. data/data/maglove/scaffold/base/less/vendor/magnific-popup.less +363 -0
  46. data/data/maglove/scaffold/base/less/widgets/banner.less +3 -0
  47. data/data/maglove/scaffold/base/less/widgets/button.less +26 -0
  48. data/data/maglove/scaffold/base/less/widgets/callout.less +3 -0
  49. data/data/maglove/scaffold/base/less/widgets/columns.less +25 -0
  50. data/data/maglove/scaffold/base/less/widgets/container.less +114 -0
  51. data/data/maglove/scaffold/base/less/widgets/feedback.less +11 -0
  52. data/data/maglove/scaffold/base/less/widgets/heading.less +8 -0
  53. data/data/maglove/scaffold/base/less/widgets/horizontal_rule.less +113 -0
  54. data/data/maglove/scaffold/base/less/widgets/image.less +85 -0
  55. data/data/maglove/scaffold/base/less/widgets/paragraph.less +3 -0
  56. data/data/maglove/scaffold/base/variables.less +75 -0
  57. data/data/maglove/scaffold/base/vendor/jquery.js +4 -0
  58. data/data/maglove/scaffold/theme/images/logo.png +0 -0
  59. data/data/maglove/scaffold/theme/images/pattern/symphony.png +0 -0
  60. data/data/maglove/scaffold/theme/less/base/variables.less +25 -0
  61. data/data/maglove/scaffold/theme/templates/article-01.haml +41 -0
  62. data/data/maglove/scaffold/theme/templates/cover.haml +27 -0
  63. data/data/maglove/scaffold/theme/templates/toc.haml +34 -0
  64. data/data/maglove/scaffold/theme/templates/toc.yml +12 -0
  65. data/data/maglove/scaffold/theme/theme.coffee +1 -0
  66. data/data/maglove/scaffold/theme/theme.less +4 -0
  67. data/data/maglove/sdk.coffee +22 -0
  68. data/data/maglove/sdk.haml +18 -0
  69. data/data/maglove/sdk.less +60 -0
  70. data/data/maglove/thumbnail.haml +11 -0
  71. data/data/maglove/thumbnail.js +160 -0
  72. data/data/maglove/vendor.js +4 -0
  73. data/lib/ext/commander/command.rb +32 -0
  74. data/lib/ext/commander/methods.rb +8 -0
  75. data/lib/maglove/application.rb +46 -0
  76. data/lib/maglove/asset/base_theme.rb +17 -0
  77. data/lib/maglove/asset/theme.rb +83 -0
  78. data/lib/maglove/command/compile.rb +40 -0
  79. data/lib/maglove/command/compress.rb +36 -0
  80. data/lib/maglove/command/copy.rb +35 -0
  81. data/lib/maglove/command/core.rb +23 -0
  82. data/lib/maglove/command/font.rb +80 -0
  83. data/lib/maglove/command/server.rb +16 -0
  84. data/lib/maglove/command/sync.rb +17 -0
  85. data/lib/maglove/command/theme.rb +132 -0
  86. data/lib/maglove/command/util.rb +45 -0
  87. data/lib/maglove/helper/asset_helper.rb +24 -0
  88. data/lib/maglove/helper/command_helper.rb +67 -0
  89. data/lib/maglove/helper/log_helper.rb +42 -0
  90. data/lib/maglove/helper/theme_helper.rb +101 -0
  91. data/lib/maglove/phantom_script.rb +45 -0
  92. data/lib/maglove/server.rb +80 -0
  93. data/lib/maglove/template/tumblr.rb +81 -0
  94. data/lib/maglove/tilt/coffee_template.rb +47 -0
  95. data/lib/maglove/tilt/haml_template.rb +20 -0
  96. data/lib/maglove/tilt/js_template.rb +38 -0
  97. data/lib/maglove/tilt/less_template.rb +18 -0
  98. data/lib/maglove/tilt/twig_template.rb +49 -0
  99. data/lib/maglove/tilt/yaml_template.rb +19 -0
  100. data/lib/maglove/version.rb +3 -0
  101. data/lib/maglove.rb +46 -0
  102. data/maglove.gemspec +39 -0
  103. metadata +427 -0
@@ -0,0 +1,83 @@
1
+ module MagLove
2
+ module Asset
3
+ class Theme
4
+ include MagLove::Helper::AssetHelper
5
+ include MagLove::Helper::LogHelper
6
+ include MagLove::Helper::ThemeHelper
7
+ attr_reader :mtime, :path, :theme, :valid, :locals, :contents
8
+
9
+ OUTPUT_MAPPING = {
10
+ "haml" => "html",
11
+ "twig" => "html",
12
+ "less" => "css",
13
+ "coffee" => "js",
14
+ "yml" => "json"
15
+ }
16
+
17
+ def initialize(path, theme, locals={})
18
+ @path = path
19
+ @theme = theme
20
+ @locals = locals
21
+ @mtime = File.mtime(absolute_path)
22
+ begin
23
+ if ::Tilt[input_type]
24
+ template = ::Tilt.new(absolute_path)
25
+ locals[:base_path] = theme_base_path(nil, theme)
26
+ @contents = template.render(nil, locals)
27
+ else
28
+ @contents = File.read(absolute_path)
29
+ end
30
+ rescue Exception => e
31
+ error("▸ #{e.message}")
32
+ end
33
+ end
34
+
35
+ def input_type
36
+ File.extname(path).gsub("\.", "")
37
+ end
38
+
39
+ def output_type
40
+ OUTPUT_MAPPING[input_type] or input_type
41
+ end
42
+
43
+ def valid?
44
+ !contents.nil?
45
+ end
46
+
47
+ def write!
48
+ return false if not valid?
49
+ FileUtils.mkdir_p(File.dirname(output_path))
50
+
51
+ File.open("#{output_path}+", 'wb') do |f|
52
+ f.write @contents
53
+ end
54
+
55
+ # Atomic write
56
+ FileUtils.mv("#{output_path}+", output_path)
57
+
58
+ # Set mtime correctly
59
+ File.utime(mtime, mtime, output_path)
60
+
61
+ true
62
+ ensure
63
+ # Ensure tmp file gets cleaned up
64
+ FileUtils.rm("#{output_path}+") if File.exist?("#{output_path}+")
65
+ end
66
+
67
+ def absolute_path
68
+ File.absolute_path("src/themes/#{theme}/#{path}")
69
+ end
70
+
71
+ def logical_path
72
+ return false if not valid?
73
+ "#{File.dirname(path)}/#{File.basename(path,'.*')}.#{output_type}"
74
+ end
75
+
76
+ def output_path
77
+ return false if not valid?
78
+ "dist/themes/#{theme}/#{logical_path}"
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,40 @@
1
+ module MagLove
2
+ module Command
3
+ class Compile
4
+ include Commander::Methods
5
+
6
+ def run
7
+
8
+ task :coffee, theme: "!" do |args, options|
9
+ asset = theme_asset("theme.coffee", options.theme)
10
+ debug("▸ created #{asset.logical_path}") if asset.write!
11
+ end
12
+
13
+ task :less, theme: "!" do |args, options|
14
+ asset = theme_asset("theme.less", options.theme)
15
+ debug("▸ created #{asset.logical_path}") if asset.write!
16
+ end
17
+
18
+ task :yaml, theme: "!" do |args, options|
19
+ asset = theme_asset("theme.yml", options.theme)
20
+ debug("▸ created #{asset.logical_path}") if asset.write!
21
+ end
22
+
23
+ task :templates, theme: "!", bucket: "!" do |args, options|
24
+ Hamloft::Options.defaults[:asset_uri] = "http://#{options.bucket}"
25
+ theme_glob("templates/*.{html,haml,twig}", options.theme).each do |file|
26
+ # check if yaml file exists
27
+ locals = {}
28
+ locals_contents = theme_contents(file.sub(/\.[^.]+\z/, ".yml"), options.theme)
29
+ if locals_contents
30
+ locals = YAML.load(locals_contents).with_indifferent_access
31
+ end
32
+ asset = theme_asset(file, options.theme, locals)
33
+ debug("▸ created #{asset.logical_path}") if asset.write!
34
+ end
35
+ end
36
+
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ module MagLove
2
+ module Command
3
+ class Compress
4
+ include Commander::Methods
5
+
6
+ def run
7
+
8
+ task :theme, theme: "!" do |args, options|
9
+ # archive_path("dist/themes/#{options.theme}", "**/*", "#{options.theme}.tar.gz")
10
+ target = "themes/#{options.theme}/#{options.theme}.tar.gz"
11
+ Dir.chdir("dist") do
12
+ tgz = Zlib::GzipWriter.new(File.open(target, "wb"))
13
+ Archive::Tar::Minitar::Output.open(tgz) do |tar|
14
+ Dir["themes/#{options.theme}/**/*"].reject{|file| file == target}.each do |file|
15
+ Archive::Tar::Minitar::pack_file(file, tar)
16
+ end
17
+ end
18
+ end
19
+
20
+ # Dir.chdir(path) do
21
+ # tgz = Zlib::GzipWriter.new(File.open(target, 'wb'))
22
+ # Archive::Tar::Minitar::Output.open(tgz) do |tar|
23
+ # Dir[pattern].reject{|file| file == target}.each do |file|
24
+ # Archive::Tar::Minitar::pack_file(file, tar)
25
+ # end
26
+ # end
27
+ # end
28
+
29
+
30
+ debug("▸ created #{options.theme}.tar.gz")
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ module MagLove
2
+ module Command
3
+ class Copy
4
+ include Commander::Methods
5
+
6
+ def run
7
+
8
+ task :base_images, theme: "!", pattern: "images/**/*.{jpg,png,gif,svg}" do |args, options|
9
+ pattern = options.pattern.gsub(theme_base_path("", options.theme), "")
10
+ theme_base_glob(pattern, options.theme).each do |file|
11
+ asset = base_theme_asset(file, options.theme)
12
+ debug("▸ created #{asset.logical_path}") if asset.write!
13
+ end
14
+ end
15
+
16
+ task :images, theme: "!", pattern: "images/**/*.{jpg,png,gif,svg}" do |args, options|
17
+ pattern = options.pattern.gsub(theme_path("", options.theme), "")
18
+ theme_glob(pattern, options.theme).each do |file|
19
+ asset = theme_asset(file, options.theme)
20
+ debug("▸ created #{asset.logical_path}") if asset.write!
21
+ end
22
+ end
23
+
24
+ task :thumbs, theme: "!", pattern: "thumbs/**/*.{jpg,png,gif,svg}" do |args, options|
25
+ pattern = options.pattern.gsub(theme_path("", options.theme), "")
26
+ theme_glob(pattern, options.theme).each do |file|
27
+ asset = theme_asset(file, options.theme)
28
+ debug("▸ created #{asset.logical_path}") if asset.write!
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ module MagLove
2
+ module Command
3
+ class Core
4
+ include Commander::Methods
5
+
6
+ def run
7
+
8
+ task :validate, theme: "!" do |args, options|
9
+ error! "no theme specified" if !options.theme
10
+ error! "theme #{options.theme} does not exist" if !File.directory?("src/themes/#{options.theme}")
11
+ debug("theme: #{options.theme}")
12
+ debug("environment: #{options.production ? 'production' : 'development'}")
13
+ end
14
+
15
+ task :clean, theme: "!" do |args, options|
16
+ theme_clean(options.theme)
17
+ debug("▸ cleaned up theme directory")
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,80 @@
1
+ module MagLove
2
+ module Command
3
+ class Font
4
+ include Commander::Methods
5
+
6
+ def get_font_styles(font_id, variant, append_dir='')
7
+ font_name = font_id.gsub('-', ' ').titleize
8
+ case variant
9
+ when "regular"
10
+ "@font-face{font-family:'#{font_name}';src:url('#{append_dir}#{font_id}-#{variant}.ttf');}\n"
11
+ when "bold"
12
+ "@font-face{font-family:'#{font_name}';src:url('#{append_dir}#{font_id}-#{variant}.ttf');font-weight:bold;}\n"
13
+ when "italic"
14
+ "@font-face{font-family:'#{font_name}';src:url('#{append_dir}#{font_id}-#{variant}.ttf');font-style:italic;}\n"
15
+ when "bolditalic"
16
+ "@font-face{font-family:'#{font_name}';src:url('#{append_dir}#{font_id}-#{variant}.ttf');font-weight:bold;font-style:italic;}\n"
17
+ when "light"
18
+ "@font-face{font-family:'#{font_name}';src:url('#{append_dir}#{font_id}-#{variant}.ttf');font-weight:300;}\n"
19
+ end
20
+ end
21
+
22
+ def run
23
+
24
+ task :compile, bucket: "cdn.magloft.com", sync: "NO" do |args, options|
25
+
26
+ # clean up
27
+ FileUtils.rm_rf("dist/fonts")
28
+ FileUtils.mkdir_p("dist/fonts")
29
+
30
+ # 1: Build font map
31
+ debug("▸ building font map")
32
+ font_map = {}
33
+ font_files = Dir.glob("src/fonts/*/*.ttf")
34
+ font_files.each do |font_file|
35
+ (root_dir, font_dir, font_id, font_filename) = font_file.split("/")
36
+ font_variant = font_filename.gsub("#{font_id}-", '').gsub(".ttf", '')
37
+ font_map[font_id] = [] if font_map[font_id].nil?
38
+ font_map[font_id].push(font_variant)
39
+ end
40
+
41
+ # 2: Generate stylesheets
42
+ debug("▸ compiling fonts:")
43
+ FileUtils.touch("dist/fonts/fonts.css")
44
+ open("dist/fonts/fonts.css", 'wb') do |master_file|
45
+ font_map.each do |font_id, variants|
46
+ debug("~▸ compiling font '#{font_id}'")
47
+
48
+ # Create font directory
49
+ FileUtils.mkdir_p("dist/fonts/#{font_id}")
50
+
51
+ # Copy fonts
52
+ variants.each do |variant|
53
+ FileUtils.copy("src/fonts/#{font_id}/#{font_id}-#{variant}.ttf", "dist/fonts/#{font_id}/#{font_id}-#{variant}.ttf")
54
+ end
55
+
56
+ # Create stylesheet
57
+ font_style_file = "dist/fonts/#{font_id}/font.css"
58
+ FileUtils.touch(font_style_file)
59
+ open(font_style_file, 'wb') do |file|
60
+ master_file << "/* #{font_id} (#{variants.join(", ")}) */\n"
61
+ variants.each do |variant|
62
+ file << get_font_styles(font_id, variant)
63
+ master_file << get_font_styles(font_id, variant, "#{font_id}/")
64
+ end
65
+ master_file << "\n"
66
+ end
67
+ end
68
+ end
69
+ debug("▸ all font styles created")
70
+
71
+ if options.sync == "YES"
72
+ system "gsutil -m rsync -d -r dist/fonts gs://#{options.bucket}/fonts"
73
+ debug("▸ all fonts synchronized with bucket '#{options.bucket}'")
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,16 @@
1
+ module MagLove
2
+ module Command
3
+ class Server
4
+ include Commander::Methods
5
+
6
+ def run
7
+
8
+ task :run, theme: "!" do |args, options|
9
+ info("▸ starting server for theme '#{options.theme}'")
10
+ MagLove::Server.new(options.theme).run!
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ module MagLove
2
+ module Command
3
+ class Sync
4
+ include Commander::Methods
5
+
6
+ def run
7
+
8
+ task :cdn, theme: "!", bucket: "test-cdn.magloft.com" do |args, options|
9
+ error! "theme '#{options.theme}' does not exist. Did you run theme:compile yet?" if !options.theme or !File.directory?("dist/themes/#{options.theme}")
10
+ info("▸ synchronizing #{options.theme} to #{options.bucket}")
11
+ system "gsutil -m rsync -d -r dist/themes/#{options.theme} gs://#{options.bucket}/themes/#{options.theme}"
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,132 @@
1
+ module MagLove
2
+ module Command
3
+ class Theme
4
+ include Commander::Methods
5
+
6
+ def run
7
+
8
+ task :compile, theme: ENV["THEME"], sync: "NO", bucket: "localhost:3002" do |args, options|
9
+ info("▸ compiling theme #{options.theme}")
10
+ invoke_tasks(["core:validate", "core:clean", "compile:coffee", "compile:less", "compile:yaml", "compile:templates", "copy:base_images", "copy:images", "copy:thumbs", "compress:theme"], options)
11
+
12
+ if options.sync == "YES"
13
+ error!("▸ SYNC error: please specify a bucket to use (cdn.magloft.com, test-cdn.magloft.com)") if options.bucket == "localhost:3001"
14
+ invoke_task("sync:cdn", options)
15
+ end
16
+
17
+ end
18
+
19
+ task :"compile-all", sync: "NO", bucket: "localhost:3002" do |args, options|
20
+ themes = Dir.chdir("src/themes") { Dir.glob("*") }
21
+ themes.each do |theme|
22
+ options.theme = theme
23
+ invoke_task("theme:compile", options)
24
+ end
25
+ end
26
+
27
+ task :thumbnails, theme: ENV["THEME"] do |args, options|
28
+ info("▸ Starting Server")
29
+ Thread.new do
30
+ MagLove::Server.new(options.theme, 3000).run!
31
+ end
32
+ sleep 1
33
+
34
+ info("▸ Generating thumbnails for theme '#{options.theme}'")
35
+
36
+ templates = theme_config(:templates, options.theme)
37
+ templates.each do |template|
38
+ debug "▸ processing template #{template}"
39
+
40
+ variables = {}
41
+ variables_yaml = theme_contents("templates/#{template}.yml", options.theme)
42
+ variables = YAML.load(variables_yaml).with_indifferent_access if variables_yaml
43
+ variables[:theme] = options.theme
44
+
45
+ # Render template
46
+ template_file = theme_glob("templates/#{template}.{html,twig,haml}", options.theme).first
47
+ if !template_file.nil?
48
+ asset = MagLove::Asset::Theme.new(template_file, options.theme, variables)
49
+ contents = asset.contents
50
+ else
51
+ contents = "<p style='text-align: center; margin-top: 12px;'>ERROR: Template '#{template}' not found!</p>"
52
+ end
53
+
54
+ # Render thumbnail html
55
+ haml_contents = File.read(File.join(Gem.datadir("maglove"), "thumbnail.haml"))
56
+ html = Hamloft.render(haml_contents, theme: options.theme, contents: contents)
57
+
58
+ # Create thumbnail image
59
+ script = PhantomScript.new('thumbnail')
60
+ html_base64 = Base64.strict_encode64(html)
61
+ contents = script.run(html_base64, "png", "480", "640", "1")
62
+ theme_write_contents("thumbs/#{template}.png", contents, options.theme)
63
+
64
+ # Optimize thumbnail image
65
+ info("▸ Optimize image")
66
+ begin
67
+ image_optim = ImageOptim.new(pngout: false, svgo: false)
68
+ image_optim.optimize_image!(theme_path("thumbs/#{template}.png", options.theme))
69
+ rescue Exception => e
70
+ error(e.message)
71
+ error!("Missing image optimization binaries. Install via: gem install image_optim_pack")
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+
78
+ task :init, theme: ENV["THEME"], base_version: "v1" do |args, options|
79
+ # validate theme
80
+ error! "no theme specified" if !options.theme
81
+ error! "theme #{options.theme} already exists" if File.directory?("src/themes/#{options.theme}")
82
+ debug("theme: #{options.theme}")
83
+ debug("environment: #{options.production ? 'production' : 'development'}")
84
+
85
+ # collect variables
86
+ base_scaffold_dir = File.join(Gem.datadir("maglove"), "scaffold/base")
87
+ base_target_dir = "src/base/#{options.base_version}"
88
+ theme_scaffold_dir = File.join(Gem.datadir("maglove"), "scaffold/theme")
89
+ theme_target_dir = "src/themes/#{options.theme}"
90
+
91
+ # create base repository
92
+ if !File.directory?(base_target_dir)
93
+ FileUtils.mkdir_p("src/base")
94
+ FileUtils.cp_r(base_scaffold_dir, base_target_dir)
95
+ info("▸ created base theme in '#{base_target_dir}'")
96
+ end
97
+
98
+ # create theme repository
99
+ FileUtils.mkdir_p("src/themes")
100
+ FileUtils.cp_r(theme_scaffold_dir, theme_target_dir)
101
+
102
+ # create yaml file
103
+ yaml_contents = {
104
+ "name" => options.theme.titlecase,
105
+ "base_version" => options.base_version,
106
+ "identifier" => options.theme,
107
+ "description" => "#{options.theme.titlecase} theme created with MagLove",
108
+ "templates" => ['cover', 'toc', 'article-01']
109
+ }
110
+ theme_write_contents("theme.yml", yaml_contents.to_yaml.gsub("---\n", ''), options.theme)
111
+ info("▸ created #{options.theme} theme in '#{theme_target_dir}'")
112
+ end
113
+
114
+ task :dev, theme: ENV["THEME"] do |args, options|
115
+ options.production = false
116
+ invoke_task("theme:compile", options)
117
+ invoke_task("font:compile", options)
118
+ options.block = "NO"
119
+ invoke_task("util:watch", options)
120
+
121
+ # browser sync
122
+ options.files = "dist/themes/#{options.theme}/*.css, dist/themes/#{options.theme}/*.js, dist/themes/#{options.theme}/templates/*.html, dist/themes/#{options.theme}/images/**/*"
123
+ options.start_path = theme_config(:templates, options.theme).first
124
+ invoke_task("util:browser_sync", options)
125
+
126
+ invoke_task("server:run", options)
127
+ end
128
+
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,45 @@
1
+ module MagLove
2
+ module Command
3
+ class Util
4
+ include Commander::Methods
5
+
6
+ def run
7
+
8
+ task :cache_clear, bucket: "cdn.magloft.com" do |args, options|
9
+ debug("▸ clearing cache for #{options.bucket}.magloft.com")
10
+ system "gsutil -m setmeta -R -h 'Cache-Control:public, max-age=0, no-transform' gs://#{options.bucket}.magloft.com/themes"
11
+ end
12
+
13
+ task :browser_sync, theme: "!", files: "!", port: "3002", proxy_port: "3001", host: "localhost", start_path: "/", log_level: "silent" do |args, options|
14
+ debug("▸ starting browser-sync")
15
+ job = fork do
16
+ begin
17
+ system "browser-sync start --proxy #{options.host}:#{options.proxy_port} --port #{options.port} --files '#{options.files}' --startPath '#{options.start_path}' --logLevel #{options.log_level} --no-ui"
18
+ rescue Exception => e
19
+ info("▸ shutting down browser sync")
20
+ end
21
+ end
22
+ Process.detach(job)
23
+ end
24
+
25
+ task :watch, theme: "!", block: "NO" do |args, options|
26
+ info("▸ watching theme #{options.theme}")
27
+ watch_config({
28
+ "compile:coffee" => [theme_path("**/*.{coffee,js}", options.theme), theme_base_path("**/*.{coffee,js}", options.theme)],
29
+ "compile:less" => [theme_path("**/*.{less,css}", options.theme), theme_base_path("**/*.{less,css}", options.theme)],
30
+ "compile:templates" => [theme_path("**/*.{haml,twig,html}", options.theme)],
31
+ "copy:base_images" => theme_base_path("images/**/*.{jpg,jpeg,gif,png,svg}", options.theme),
32
+ "copy:images" => theme_path("images/**/*.{jpg,jpeg,gif,png,svg}", options.theme)
33
+ }, options)
34
+
35
+ if options.block == "YES"
36
+ while true
37
+ sleep 100
38
+ end
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,24 @@
1
+ module MagLove
2
+ module Helper
3
+ module AssetHelper
4
+
5
+ def theme_asset(path, theme=nil, locals={})
6
+ theme ||= ENV["THEME"]
7
+ if not File.exists?("src/themes/#{theme}/#{path}")
8
+ error! "file '#{path}' not found for theme '#{theme}'"
9
+ end
10
+ MagLove::Asset::Theme.new(path, theme, locals.merge(theme: theme))
11
+ end
12
+
13
+ def base_theme_asset(path, theme=nil, version=nil)
14
+ theme ||= ENV["THEME"]
15
+ version ||= theme_config("base_version", theme)
16
+ if not File.exists?("src/base/#{version}/#{path}")
17
+ error! "file '#{path}' not found for base-theme '#{version}'"
18
+ end
19
+ MagLove::Asset::BaseTheme.new(path, theme, version)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,67 @@
1
+ module MagLove
2
+ module Helper
3
+ module CommandHelper
4
+
5
+ def task(action, option_config={}, &block)
6
+ command "#{library}-#{action}" do |c|
7
+ required_options = []
8
+ c.syntax = "maglove #{library} #{action}"
9
+ c.summary = "#{library} #{action} command"
10
+ option_config.each do |key, value|
11
+ if value == "!"
12
+ required_options.push(key)
13
+ c.option "--#{key} STRING", String, "[required]"
14
+ else
15
+ c.option "--#{key} STRING", String, "[default: #{value}]"
16
+ end
17
+ end
18
+ c.task_action do |args, options|
19
+ Logging.mdc["command"] = "#{library}-#{action}"
20
+ required_options.each do |required_option|
21
+ if !options.__hash__[required_option.to_sym]
22
+ error!("missing required option '#{required_option}'")
23
+ end
24
+ end
25
+ options.default(option_config)
26
+ block.call(args, options)
27
+ end
28
+ end
29
+ end
30
+
31
+ def library
32
+ self.class.name.split("::").last.underscore
33
+ end
34
+
35
+ def invoke_tasks(command_names, *args)
36
+ command_names.each do |command_name|
37
+ invoke_task(command_name, *args)
38
+ end
39
+ end
40
+
41
+ def invoke_task(command_name, *args)
42
+ command_name = command_name.gsub(":", "-")
43
+ if args.length == 0
44
+ command_args = []
45
+ command_options = Commander::Command::Options.new
46
+ elsif args.length == 1
47
+ if args[0].class == Array
48
+ command_args = args[0]
49
+ command_options = Commander::Command::Options.new
50
+ else
51
+ command_args = []
52
+ command_options = args[0]
53
+ end
54
+ elsif args.length == 2
55
+ command_args = args[0]
56
+ command_options = Commander::Command::Options.new
57
+ else
58
+ error!("invalid arguments specified for invoke_task '#{command_name}'")
59
+ end
60
+ command = Commander::Runner.instance.commands[command_name]
61
+ error!("cannot invoke command '#{command_name}': command not found") if command.nil?
62
+ command.invoke(command_args, command_options)
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,42 @@
1
+ module MagLove
2
+ module Helper
3
+ module LogHelper
4
+ @@logger = nil
5
+
6
+ def info(message)
7
+ logger.send(:info, message)
8
+ end
9
+
10
+ def debug(message)
11
+ logger.send(:debug, message)
12
+ end
13
+
14
+ def error(message)
15
+ logger.send(:error, message)
16
+ end
17
+
18
+ def error!(message)
19
+ logger.send(:fatal, message)
20
+ Kernel.exit
21
+ end
22
+
23
+ def logger
24
+ # reset logger on task change
25
+ if @@logger.nil?
26
+ Logging.color_scheme("bright",
27
+ levels: { debug: :blue, info: :green, warn: :yellow, error: :red, fatal: [:white, :on_red] },
28
+ date: :blue,
29
+ mdc: :cyan,
30
+ logger: :cyan,
31
+ message: :black
32
+ )
33
+ Logging.appenders.stdout("stdout", layout: Logging.layouts.pattern( pattern: '[%d] %-5l %-16X{command} %x %m\n', color_scheme: 'bright' ))
34
+ @@logger = Logging::Logger.new(self.class.name)
35
+ @@logger.level = :info
36
+ @@logger.add_appenders('stdout')
37
+ end
38
+ @@logger
39
+ end
40
+ end
41
+ end
42
+ end