maglove 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +137 -0
- data/README.md +26 -0
- data/bin/maglove +21 -0
- data/data/maglove/scaffold/base/base.coffee +1 -0
- data/data/maglove/scaffold/base/base.less +26 -0
- data/data/maglove/scaffold/base/images/base/loading-bars.svg +17 -0
- data/data/maglove/scaffold/base/less/base/animations.less +301 -0
- data/data/maglove/scaffold/base/less/base/blockquotes.less +23 -0
- data/data/maglove/scaffold/base/less/base/buttons.less +76 -0
- data/data/maglove/scaffold/base/less/base/code.less +19 -0
- data/data/maglove/scaffold/base/less/base/forms.less +115 -0
- data/data/maglove/scaffold/base/less/base/global.less +142 -0
- data/data/maglove/scaffold/base/less/base/grid-minimal.less +146 -0
- data/data/maglove/scaffold/base/less/base/grid-non-responsive.less +63 -0
- data/data/maglove/scaffold/base/less/base/grid.less +267 -0
- data/data/maglove/scaffold/base/less/base/helpers.less +146 -0
- data/data/maglove/scaffold/base/less/base/images.less +8 -0
- data/data/maglove/scaffold/base/less/base/lists.less +23 -0
- data/data/maglove/scaffold/base/less/base/mixins.less +107 -0
- data/data/maglove/scaffold/base/less/base/print.less +35 -0
- data/data/maglove/scaffold/base/less/base/resets.less +27 -0
- data/data/maglove/scaffold/base/less/base/tables.less +29 -0
- data/data/maglove/scaffold/base/less/core/alignments.less +17 -0
- data/data/maglove/scaffold/base/less/core/cleanup.less +8 -0
- data/data/maglove/scaffold/base/less/core/editor.less +23 -0
- data/data/maglove/scaffold/base/less/core/typography.less +74 -0
- data/data/maglove/scaffold/base/less/vendor/flex-video.less +22 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/animated.less +34 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/bordered-pulled.less +16 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/core.less +13 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/fixed-width.less +6 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/font-awesome.less +17 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/icons.less +596 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/larger.less +13 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/list.less +19 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/mixins.less +27 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/rotated-flipped.less +20 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/stacked.less +20 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome/variables.less +606 -0
- data/data/maglove/scaffold/base/less/vendor/font-awesome.less +16 -0
- data/data/maglove/scaffold/base/less/vendor/image-loader.less +15 -0
- data/data/maglove/scaffold/base/less/vendor/magnific-popup.less +363 -0
- data/data/maglove/scaffold/base/less/widgets/banner.less +3 -0
- data/data/maglove/scaffold/base/less/widgets/button.less +26 -0
- data/data/maglove/scaffold/base/less/widgets/callout.less +3 -0
- data/data/maglove/scaffold/base/less/widgets/columns.less +25 -0
- data/data/maglove/scaffold/base/less/widgets/container.less +114 -0
- data/data/maglove/scaffold/base/less/widgets/feedback.less +11 -0
- data/data/maglove/scaffold/base/less/widgets/heading.less +8 -0
- data/data/maglove/scaffold/base/less/widgets/horizontal_rule.less +113 -0
- data/data/maglove/scaffold/base/less/widgets/image.less +85 -0
- data/data/maglove/scaffold/base/less/widgets/paragraph.less +3 -0
- data/data/maglove/scaffold/base/variables.less +75 -0
- data/data/maglove/scaffold/base/vendor/jquery.js +4 -0
- data/data/maglove/scaffold/theme/images/logo.png +0 -0
- data/data/maglove/scaffold/theme/images/pattern/symphony.png +0 -0
- data/data/maglove/scaffold/theme/less/base/variables.less +25 -0
- data/data/maglove/scaffold/theme/templates/article-01.haml +41 -0
- data/data/maglove/scaffold/theme/templates/cover.haml +27 -0
- data/data/maglove/scaffold/theme/templates/toc.haml +34 -0
- data/data/maglove/scaffold/theme/templates/toc.yml +12 -0
- data/data/maglove/scaffold/theme/theme.coffee +1 -0
- data/data/maglove/scaffold/theme/theme.less +4 -0
- data/data/maglove/sdk.coffee +22 -0
- data/data/maglove/sdk.haml +18 -0
- data/data/maglove/sdk.less +60 -0
- data/data/maglove/thumbnail.haml +11 -0
- data/data/maglove/thumbnail.js +160 -0
- data/data/maglove/vendor.js +4 -0
- data/lib/ext/commander/command.rb +32 -0
- data/lib/ext/commander/methods.rb +8 -0
- data/lib/maglove/application.rb +46 -0
- data/lib/maglove/asset/base_theme.rb +17 -0
- data/lib/maglove/asset/theme.rb +83 -0
- data/lib/maglove/command/compile.rb +40 -0
- data/lib/maglove/command/compress.rb +36 -0
- data/lib/maglove/command/copy.rb +35 -0
- data/lib/maglove/command/core.rb +23 -0
- data/lib/maglove/command/font.rb +80 -0
- data/lib/maglove/command/server.rb +16 -0
- data/lib/maglove/command/sync.rb +17 -0
- data/lib/maglove/command/theme.rb +132 -0
- data/lib/maglove/command/util.rb +45 -0
- data/lib/maglove/helper/asset_helper.rb +24 -0
- data/lib/maglove/helper/command_helper.rb +67 -0
- data/lib/maglove/helper/log_helper.rb +42 -0
- data/lib/maglove/helper/theme_helper.rb +101 -0
- data/lib/maglove/phantom_script.rb +45 -0
- data/lib/maglove/server.rb +80 -0
- data/lib/maglove/template/tumblr.rb +81 -0
- data/lib/maglove/tilt/coffee_template.rb +47 -0
- data/lib/maglove/tilt/haml_template.rb +20 -0
- data/lib/maglove/tilt/js_template.rb +38 -0
- data/lib/maglove/tilt/less_template.rb +18 -0
- data/lib/maglove/tilt/twig_template.rb +49 -0
- data/lib/maglove/tilt/yaml_template.rb +19 -0
- data/lib/maglove/version.rb +3 -0
- data/lib/maglove.rb +46 -0
- data/maglove.gemspec +39 -0
- 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
|