savory_theme 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -0
- data/README.md +1 -0
- data/bin/savory-theme +42 -0
- data/files/Rakefile.erb +8 -0
- data/files/app/views/pages/404.liquid +1 -0
- data/files/app/views/pages/articles/content_type_template.liquid +3 -0
- data/files/app/views/pages/articles.liquid +3 -0
- data/files/app/views/pages/contents.liquid +1 -0
- data/files/app/views/pages/cover.liquid +3 -0
- data/files/app/views/pages/index.liquid +1 -0
- data/files/app/views/pages/layout.liquid +1 -0
- data/files/app/views/pages/resources.liquid +1 -0
- data/files/app/views/templates/figure.html +8 -0
- data/files/config/compiled_site.yml +159 -0
- data/files/config/locales/en.yml +22 -0
- data/files/config/theme_config.yml +66 -0
- data/files/data/articles.yml +1 -0
- data/files/data/covers.yml +1 -0
- data/lib/savory/theme/bom.rb +80 -0
- data/lib/savory/theme/exec.rb +85 -0
- data/lib/savory/theme/layout/legacy.rb +25 -0
- data/lib/savory/theme/layout/treesaver.rb +28 -0
- data/lib/savory/theme/layout.rb +4 -0
- data/lib/savory/theme/packager/features/compass.rb +27 -0
- data/lib/savory/theme/packager/features/sass.rb +27 -0
- data/lib/savory/theme/packager/features.rb +36 -0
- data/lib/savory/theme/packager.rb +80 -0
- data/lib/savory/theme/theme_task.rb +127 -0
- data/lib/savory/theme/version.rb +5 -0
- data/lib/savory/theme.rb +10 -0
- data/lib/savory_theme.rb +1 -0
- metadata +97 -0
data/LICENSE
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Savory theme support
|
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Savory theme support
|
data/bin/savory-theme
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
def fallback_load_path(path)
|
4
|
+
retried = false
|
5
|
+
begin
|
6
|
+
yield
|
7
|
+
rescue LoadError
|
8
|
+
unless retried
|
9
|
+
$: << path
|
10
|
+
retried = true
|
11
|
+
retry
|
12
|
+
end
|
13
|
+
raise
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
fallback_load_path(File.join(File.dirname(__FILE__), '..', 'lib')) do
|
18
|
+
require 'savory/theme'
|
19
|
+
require 'savory/theme/exec'
|
20
|
+
end
|
21
|
+
|
22
|
+
runner = Proc.new do
|
23
|
+
Savory::Theme::Exec.new(ARGV).run!
|
24
|
+
end
|
25
|
+
|
26
|
+
if ARGV.delete("--profile")
|
27
|
+
require 'ruby-prof'
|
28
|
+
RubyProf.start
|
29
|
+
exit_code = runner.call
|
30
|
+
result = RubyProf.stop
|
31
|
+
|
32
|
+
# Print a flat profile to text
|
33
|
+
printer = RubyProf::FlatPrinter.new(result)
|
34
|
+
printer.print(STDERR, 0)
|
35
|
+
exit exit_code
|
36
|
+
else
|
37
|
+
if exit_code = runner.call
|
38
|
+
exit exit_code
|
39
|
+
else
|
40
|
+
exit 1
|
41
|
+
end
|
42
|
+
end
|
data/files/Rakefile.erb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Content of the 404 page
|
@@ -0,0 +1 @@
|
|
1
|
+
contents.liquid
|
@@ -0,0 +1 @@
|
|
1
|
+
index.liquid
|
@@ -0,0 +1 @@
|
|
1
|
+
layout.liquid
|
@@ -0,0 +1 @@
|
|
1
|
+
resources.liquid
|
@@ -0,0 +1,159 @@
|
|
1
|
+
site:
|
2
|
+
name: savory
|
3
|
+
pages:
|
4
|
+
- index:
|
5
|
+
published: true
|
6
|
+
title: Issues List
|
7
|
+
listed: true
|
8
|
+
- layout:
|
9
|
+
published: false
|
10
|
+
title: Layout
|
11
|
+
listed: false
|
12
|
+
- cover:
|
13
|
+
published: true
|
14
|
+
title: Cover
|
15
|
+
listed: true
|
16
|
+
- articles:
|
17
|
+
published: true
|
18
|
+
title: articles
|
19
|
+
listed: true
|
20
|
+
- articles/content_type_template:
|
21
|
+
published: true
|
22
|
+
title: Template of an article
|
23
|
+
listed: true
|
24
|
+
content_type: articles
|
25
|
+
- resources:
|
26
|
+
published: true
|
27
|
+
title: resources
|
28
|
+
listed: true
|
29
|
+
- contents:
|
30
|
+
published: true
|
31
|
+
title: Contents
|
32
|
+
listed: true
|
33
|
+
cache_strategy: simple
|
34
|
+
response_type: application/json
|
35
|
+
- "404":
|
36
|
+
published: true
|
37
|
+
title: Page not found
|
38
|
+
listed: true
|
39
|
+
content_types:
|
40
|
+
Articles:
|
41
|
+
order_direction: asc
|
42
|
+
name: Articles
|
43
|
+
slug: articles
|
44
|
+
order_by: _position_in_list
|
45
|
+
highlighted_field_name: title
|
46
|
+
fields:
|
47
|
+
- issue:
|
48
|
+
label: Issue
|
49
|
+
kind: has_one
|
50
|
+
target: issues
|
51
|
+
- datagrid:
|
52
|
+
kind: category
|
53
|
+
label: Type
|
54
|
+
required: true
|
55
|
+
category_items:
|
56
|
+
- article
|
57
|
+
- deck:
|
58
|
+
label: Deck
|
59
|
+
kind: string
|
60
|
+
- title:
|
61
|
+
required: true
|
62
|
+
label: Title
|
63
|
+
kind: string
|
64
|
+
- subtitle:
|
65
|
+
label: Subtitle
|
66
|
+
kind: string
|
67
|
+
- author:
|
68
|
+
required: false
|
69
|
+
label: Author
|
70
|
+
kind: string
|
71
|
+
- thumbnail:
|
72
|
+
label: Thumbnail
|
73
|
+
kind: file
|
74
|
+
- body:
|
75
|
+
label: Body
|
76
|
+
kind: text
|
77
|
+
- article_width:
|
78
|
+
label: Article Width
|
79
|
+
kind: string
|
80
|
+
- article_height:
|
81
|
+
label: Article Height
|
82
|
+
kind: string
|
83
|
+
- exclude_from_sidebar:
|
84
|
+
kind: boolean
|
85
|
+
label: Exclude from Sidebar
|
86
|
+
contents: []
|
87
|
+
|
88
|
+
Covers:
|
89
|
+
order_direction: asc
|
90
|
+
name: Covers
|
91
|
+
slug: covers
|
92
|
+
order_by: created_at
|
93
|
+
highlighted_field_name: name
|
94
|
+
fields:
|
95
|
+
- issue:
|
96
|
+
label: Issue
|
97
|
+
kind: has_one
|
98
|
+
target: issues
|
99
|
+
- name:
|
100
|
+
required: true
|
101
|
+
label: Name
|
102
|
+
kind: string
|
103
|
+
- width:
|
104
|
+
label: Width
|
105
|
+
kind: string
|
106
|
+
- height:
|
107
|
+
label: Height
|
108
|
+
kind: string
|
109
|
+
- image:
|
110
|
+
required: true
|
111
|
+
label: Image
|
112
|
+
kind: file
|
113
|
+
contents: []
|
114
|
+
AppleIcons:
|
115
|
+
order_direction: asc
|
116
|
+
name: AppleIcons
|
117
|
+
slug: apple_icons
|
118
|
+
order_by: created_at
|
119
|
+
highlighted_field_name: name
|
120
|
+
fields:
|
121
|
+
- issue:
|
122
|
+
label: Issue
|
123
|
+
kind: has_one
|
124
|
+
target: issues
|
125
|
+
- name:
|
126
|
+
required: true
|
127
|
+
label: Name
|
128
|
+
kind: string
|
129
|
+
- width:
|
130
|
+
label: Width
|
131
|
+
kind: string
|
132
|
+
- height:
|
133
|
+
label: Height
|
134
|
+
kind: string
|
135
|
+
- image:
|
136
|
+
required: true
|
137
|
+
label: Image
|
138
|
+
kind: file
|
139
|
+
contents: []
|
140
|
+
|
141
|
+
Issues:
|
142
|
+
order_direction: asc
|
143
|
+
name: Issues
|
144
|
+
slug: issues
|
145
|
+
order_by: created_at
|
146
|
+
order_direction: desc
|
147
|
+
highlighted_field_name: name
|
148
|
+
fields:
|
149
|
+
- name:
|
150
|
+
required: true
|
151
|
+
label: Name
|
152
|
+
kind: string
|
153
|
+
- visible:
|
154
|
+
label: Visible
|
155
|
+
kind: boolean
|
156
|
+
- published:
|
157
|
+
label: Published
|
158
|
+
kind: boolean
|
159
|
+
contents: []
|
@@ -0,0 +1,22 @@
|
|
1
|
+
en:
|
2
|
+
admin:
|
3
|
+
custom_fields:
|
4
|
+
types:
|
5
|
+
category:
|
6
|
+
articles:
|
7
|
+
datagrid:
|
8
|
+
value:
|
9
|
+
#
|
10
|
+
# Display name for data grids. Example:
|
11
|
+
#
|
12
|
+
# feature: "Feature story"
|
13
|
+
#
|
14
|
+
|
15
|
+
string:
|
16
|
+
articles:
|
17
|
+
#
|
18
|
+
# Localization for string fields. Example:
|
19
|
+
#
|
20
|
+
# deck:
|
21
|
+
# label: Deck
|
22
|
+
# hint: "The deck is an additional title that is shown above the main title, in the first page of the article. It is also repeated on all pages after the first, in the colored bar at the top of the page."
|
@@ -0,0 +1,66 @@
|
|
1
|
+
features:
|
2
|
+
cover: true
|
3
|
+
theme_guiders: false
|
4
|
+
welcome_wizard: true
|
5
|
+
|
6
|
+
custom_fields:
|
7
|
+
categories:
|
8
|
+
editable:
|
9
|
+
articles: []
|
10
|
+
|
11
|
+
covers:
|
12
|
+
:vertical:
|
13
|
+
:ratio: 6x9
|
14
|
+
:sizes:
|
15
|
+
- :name: single
|
16
|
+
:description: single
|
17
|
+
:width: "300"
|
18
|
+
:height: "450"
|
19
|
+
- :name: double
|
20
|
+
:description: double
|
21
|
+
:width: "400"
|
22
|
+
:height: "600"
|
23
|
+
- :name: triple
|
24
|
+
:description: triple
|
25
|
+
:width: "660"
|
26
|
+
:height: "990"
|
27
|
+
- :name: quad
|
28
|
+
:description: quad
|
29
|
+
:width: "660"
|
30
|
+
:height: "990"
|
31
|
+
|
32
|
+
figures:
|
33
|
+
ratio: 4x3
|
34
|
+
min_size:
|
35
|
+
width: 275
|
36
|
+
height: 182
|
37
|
+
sizes:
|
38
|
+
single:
|
39
|
+
width: 275
|
40
|
+
height: 182
|
41
|
+
extra_width: 0
|
42
|
+
extra_height: 0
|
43
|
+
caption_height: 20
|
44
|
+
double:
|
45
|
+
width: 569
|
46
|
+
height: 380
|
47
|
+
extra_width: 0
|
48
|
+
extra_height: 0
|
49
|
+
caption_height: 20
|
50
|
+
no_treesaver:
|
51
|
+
- double
|
52
|
+
|
53
|
+
thumbnails:
|
54
|
+
articles:
|
55
|
+
image_double:
|
56
|
+
width: 608
|
57
|
+
height: 456
|
58
|
+
ratio: 4x3
|
59
|
+
image_single:
|
60
|
+
width: 296
|
61
|
+
height: 222
|
62
|
+
ratio: 4x3
|
63
|
+
image_thumb:
|
64
|
+
width: 50
|
65
|
+
height: 50
|
66
|
+
ratio: 1x1
|
@@ -0,0 +1 @@
|
|
1
|
+
[]
|
@@ -0,0 +1 @@
|
|
1
|
+
[]
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Savory::Theme
|
5
|
+
class BOM
|
6
|
+
|
7
|
+
def initialize(theme)
|
8
|
+
@theme = theme
|
9
|
+
@layout = @theme.layout
|
10
|
+
@base = @theme.res_home
|
11
|
+
@bom = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def create
|
15
|
+
@theme.layout.prepare(:bom, @base)
|
16
|
+
|
17
|
+
images
|
18
|
+
javascripts
|
19
|
+
stylesheets
|
20
|
+
|
21
|
+
write!
|
22
|
+
end
|
23
|
+
|
24
|
+
def clean
|
25
|
+
File.unlink(bom_file_path)
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
def create!(theme)
|
30
|
+
self.new(theme).create
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
def bom_file_path
|
36
|
+
"config/bom.yml"
|
37
|
+
end
|
38
|
+
|
39
|
+
def images
|
40
|
+
traverse(File.expand_path(@layout.public_images, @base)) do |file|
|
41
|
+
add(:images, file, hash(file))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def javascripts
|
46
|
+
traverse(File.expand_path(@layout.public_js, @base), "**/*.js") do |file|
|
47
|
+
add(:javascripts, file, hash(file))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def stylesheets
|
52
|
+
traverse(File.expand_path(@layout.public_css, @base), "**/*.css") do |file|
|
53
|
+
add(:stylesheets, file, hash(file))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def hash(file)
|
58
|
+
Digest::SHA1.hexdigest(File.read(file))[8,8]
|
59
|
+
end
|
60
|
+
|
61
|
+
def write!
|
62
|
+
File.open(bom_file_path, "w") do |out|
|
63
|
+
out.puts YAML.dump(@bom)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def traverse(base, glob = '**/*')
|
68
|
+
Dir.chdir(base) do
|
69
|
+
Dir['**/*'].each do |file|
|
70
|
+
yield(file) if File.file?(file)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def add(section, name, version)
|
76
|
+
@bom[section] ||= {}
|
77
|
+
@bom[section][name] = version
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module Savory::Theme
|
6
|
+
class Exec
|
7
|
+
def initialize(args)
|
8
|
+
@args = args
|
9
|
+
@force = false # XXX
|
10
|
+
@verbose = true # XXX
|
11
|
+
end
|
12
|
+
|
13
|
+
def run!
|
14
|
+
install
|
15
|
+
0
|
16
|
+
end
|
17
|
+
|
18
|
+
def install
|
19
|
+
install_rakefile
|
20
|
+
install_version
|
21
|
+
recursive_install("app")
|
22
|
+
recursive_install("config")
|
23
|
+
recursive_install("data")
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
def install_rakefile
|
28
|
+
src = File.expand_path("../../../files/Rakefile.erb", File.dirname(__FILE__))
|
29
|
+
dst = "Rakefile"
|
30
|
+
install_file(src, dst)
|
31
|
+
end
|
32
|
+
|
33
|
+
def install_version
|
34
|
+
Tempfile.open('version') do |f|
|
35
|
+
f.puts('0.1')
|
36
|
+
f.flush
|
37
|
+
install_file(f.path, "VERSION")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def recursive_install(dir)
|
42
|
+
create_dir(dir)
|
43
|
+
|
44
|
+
base = Pathname.new(File.expand_path("../../../files", File.dirname(__FILE__)))
|
45
|
+
Dir["#{base}/#{dir}/**/*"].each do |src|
|
46
|
+
dst = Pathname.new(src).relative_path_from(base)
|
47
|
+
if File.directory?(src)
|
48
|
+
create_dir(dst)
|
49
|
+
else
|
50
|
+
install_file(src, dst)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def install_file(src, dst)
|
56
|
+
exists = if @force
|
57
|
+
false
|
58
|
+
elsif File.exists?(dst)
|
59
|
+
puts "Destination file #{dst} exists, I won't override it" if @verbose
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
unless exists
|
64
|
+
if src =~ /\.erb$/
|
65
|
+
install_erb(src, dst)
|
66
|
+
else
|
67
|
+
FileUtils.cp(src, dst)
|
68
|
+
end
|
69
|
+
puts "created #{dst}" if @verbose
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def install_erb(src, dst)
|
74
|
+
File.open(dst, "w") do |f|
|
75
|
+
erb = ERB.new(File.read(src))
|
76
|
+
f.write(erb.result)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def create_dir(dir)
|
81
|
+
FileUtils.mkdir_p(dir)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Savory::Theme
|
2
|
+
module Layout
|
3
|
+
class Legacy
|
4
|
+
class << self
|
5
|
+
def prepare(phase, base)
|
6
|
+
end
|
7
|
+
|
8
|
+
def clean
|
9
|
+
end
|
10
|
+
|
11
|
+
def public_css
|
12
|
+
"public/stylesheets"
|
13
|
+
end
|
14
|
+
|
15
|
+
def public_images
|
16
|
+
"public/images"
|
17
|
+
end
|
18
|
+
|
19
|
+
def public_js
|
20
|
+
"public/javascripts"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Savory::Theme
|
5
|
+
module Layout
|
6
|
+
class Treesaver
|
7
|
+
class << self
|
8
|
+
def prepare(phase, base)
|
9
|
+
end
|
10
|
+
|
11
|
+
def clean
|
12
|
+
end
|
13
|
+
|
14
|
+
def public_css
|
15
|
+
"_/css"
|
16
|
+
end
|
17
|
+
|
18
|
+
def public_images
|
19
|
+
"_/img"
|
20
|
+
end
|
21
|
+
|
22
|
+
def public_js
|
23
|
+
"_/js"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Savory::Theme
|
2
|
+
class Packager
|
3
|
+
class Features
|
4
|
+
class Compass
|
5
|
+
def initialize(packager)
|
6
|
+
@packager = packager
|
7
|
+
end
|
8
|
+
|
9
|
+
def enabled?(theme)
|
10
|
+
theme.features[:compass]
|
11
|
+
end
|
12
|
+
|
13
|
+
def apply(theme)
|
14
|
+
puts "Compiling with compass"
|
15
|
+
|
16
|
+
out = `bundle exec compass compile --force -s #{output_style}`
|
17
|
+
if $?.to_i != 0
|
18
|
+
puts out
|
19
|
+
raise "Failed: #{$!}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
add_feature(Compass)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Savory::Theme
|
2
|
+
class Packager
|
3
|
+
class Features
|
4
|
+
class Sass
|
5
|
+
def initialize(packager)
|
6
|
+
@packager = packager
|
7
|
+
end
|
8
|
+
|
9
|
+
def enabled?(theme)
|
10
|
+
theme.features[:sass]
|
11
|
+
end
|
12
|
+
|
13
|
+
def apply(theme)
|
14
|
+
puts "Compiling with sass"
|
15
|
+
|
16
|
+
out = `sass --style compressed --update ../sass:../html` # FIXME
|
17
|
+
if $?.to_i != 0
|
18
|
+
puts out
|
19
|
+
raise "Failed: #{$!}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
add_feature(Sass)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Savory::Theme
|
2
|
+
class Packager
|
3
|
+
class Features
|
4
|
+
class << self
|
5
|
+
attr_reader :feature_klasses
|
6
|
+
|
7
|
+
def add_feature(klass)
|
8
|
+
@feature_klasses ||= []
|
9
|
+
@feature_klasses << klass
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(packager)
|
14
|
+
@packager = packager
|
15
|
+
@features = self.class.feature_klasses.map do |klass|
|
16
|
+
klass.new(packager)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def apply!(theme)
|
21
|
+
applicable = @features.select do |f|
|
22
|
+
f.enabled?(theme)
|
23
|
+
end
|
24
|
+
|
25
|
+
applicable.each do |f|
|
26
|
+
f.apply(theme)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
basedir = File.dirname(__FILE__)
|
34
|
+
Dir["#{basedir}/features/**/*.rb"].each do |f|
|
35
|
+
require f
|
36
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'savory/theme/bom'
|
2
|
+
require 'savory/theme/packager/features'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'zip/zip'
|
5
|
+
|
6
|
+
module Savory::Theme
|
7
|
+
class Packager
|
8
|
+
attr_reader :verbose
|
9
|
+
|
10
|
+
def initialize(theme, options = {})
|
11
|
+
@theme = theme
|
12
|
+
@options = options
|
13
|
+
@verbose = @options.delete(:verbose)
|
14
|
+
@features = Features.new(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
def compile!(options = {})
|
18
|
+
full_version = options.delete(:full_version)
|
19
|
+
output_style = options.delete(:output_style)
|
20
|
+
|
21
|
+
@features.apply!(@theme)
|
22
|
+
|
23
|
+
puts "Theme CSS compiled" if @verbose
|
24
|
+
end
|
25
|
+
|
26
|
+
def bom!
|
27
|
+
BOM.create!(@theme)
|
28
|
+
end
|
29
|
+
|
30
|
+
def zip!(zip_name, options = {})
|
31
|
+
@theme.layout.prepare(:zip, @theme.res_home)
|
32
|
+
home = Pathname.new(@theme.res_home)
|
33
|
+
excludes = options.delete(:exclude)
|
34
|
+
|
35
|
+
paths = {
|
36
|
+
'app' => 'app',
|
37
|
+
'config' => 'config',
|
38
|
+
'data' => 'data',
|
39
|
+
home.join(@theme.layout.public_css) => 'public/stylesheets',
|
40
|
+
home.join(@theme.layout.public_js) => 'public/javascripts',
|
41
|
+
home.join(@theme.layout.public_images) => 'public/images'
|
42
|
+
}
|
43
|
+
|
44
|
+
write_zip(zip_name, paths, excludes)
|
45
|
+
puts "Theme written to #{zip_name}" if @verbose
|
46
|
+
end
|
47
|
+
|
48
|
+
def clean
|
49
|
+
BOM.new(@theme).clean
|
50
|
+
@theme.layout.clean
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
def match_any?(input, patterns)
|
55
|
+
patterns.any? do |pattern|
|
56
|
+
input.to_s =~ Regexp.new(pattern)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def write_zip(zipname, directories, excludes=[])
|
61
|
+
FileUtils.rm(zipname) if File.exist?(zipname)
|
62
|
+
|
63
|
+
Zip::ZipFile.open(zipname, Zip::ZipFile::CREATE) do |zip|
|
64
|
+
directories.each do |src, dest|
|
65
|
+
add_directory(zip, src, dest, excludes)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_directory(zip, src_dir, dest_dir, excludes=[])
|
71
|
+
src = Pathname.new(src_dir)
|
72
|
+
dest = Pathname.new(dest_dir)
|
73
|
+
src.find do |entry|
|
74
|
+
if entry.file? && !match_any?(entry, excludes)
|
75
|
+
zip.add dest.join(entry.relative_path_from(src)), entry
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'rake/tasklib'
|
2
|
+
|
3
|
+
require 'savory/theme/layout'
|
4
|
+
|
5
|
+
module Savory::Theme
|
6
|
+
class ThemeTask < Rake::TaskLib
|
7
|
+
# The home of the theme.
|
8
|
+
attr_accessor :home
|
9
|
+
|
10
|
+
# The directory that contains all resources (images, JS, CSS).
|
11
|
+
attr_accessor :res_home
|
12
|
+
|
13
|
+
# Name of the theme.
|
14
|
+
attr_accessor :name
|
15
|
+
|
16
|
+
# Version of the theme.
|
17
|
+
attr_accessor :version
|
18
|
+
|
19
|
+
# Name of the generated zip file (default to "#{name}-#{version}.zip").
|
20
|
+
attr_accessor :zip_name
|
21
|
+
|
22
|
+
# Files to exclude from the generated zip file.
|
23
|
+
attr_accessor :excludes
|
24
|
+
|
25
|
+
# CSS output style (default to "compressed").
|
26
|
+
attr_accessor :output_style
|
27
|
+
|
28
|
+
# Verbose output (default to false).
|
29
|
+
attr_accessor :verbose
|
30
|
+
|
31
|
+
# Additional features (default to none).
|
32
|
+
attr_accessor :features
|
33
|
+
|
34
|
+
# Theme layout (default to Treesaver)
|
35
|
+
attr_accessor :layout
|
36
|
+
|
37
|
+
def initialize(path = nil)
|
38
|
+
@home ||= theme_home(caller)
|
39
|
+
@res_home ||= @home
|
40
|
+
@name = name
|
41
|
+
@version = nil
|
42
|
+
@zip_name = nil
|
43
|
+
@excludes = []
|
44
|
+
@output_style = "compressed"
|
45
|
+
@verbose = false
|
46
|
+
@features = {}
|
47
|
+
@layout = Layout::Treesaver
|
48
|
+
yield self if block_given?
|
49
|
+
define
|
50
|
+
end
|
51
|
+
|
52
|
+
def layout=(name_or_class)
|
53
|
+
case name_or_class
|
54
|
+
when String
|
55
|
+
@layout = Layout.const_get(name_or_class)
|
56
|
+
when Symbol
|
57
|
+
@layout = Layout.const_get(name_or_class.to_s.capitalize)
|
58
|
+
else
|
59
|
+
@layout = name_or_class
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def define
|
64
|
+
task :default => :zip
|
65
|
+
|
66
|
+
desc "Clean working files"
|
67
|
+
task :clean do
|
68
|
+
@version ||= theme_version
|
69
|
+
packager = Savory::Theme::Packager.new(self, :verbose => @verbose)
|
70
|
+
packager.clean
|
71
|
+
end
|
72
|
+
|
73
|
+
desc "Compile stylesheet"
|
74
|
+
task :compile do
|
75
|
+
@version ||= theme_version
|
76
|
+
packager = Savory::Theme::Packager.new(self, :verbose => @verbose)
|
77
|
+
packager.compile!(:full_version => @version, :output_style => @output_style)
|
78
|
+
end
|
79
|
+
|
80
|
+
desc "Build a zip file"
|
81
|
+
task :zip => :compile do
|
82
|
+
@zip_name ||= "#{@name}-#{@version}.zip"
|
83
|
+
packager = Savory::Theme::Packager.new(self, :verbose => @verbose)
|
84
|
+
packager.bom!
|
85
|
+
packager.zip!(@zip_name, :exclude => @excludes)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def feature(arg)
|
90
|
+
case arg
|
91
|
+
when Array
|
92
|
+
arg.each { |a| features(a) }
|
93
|
+
when Hash
|
94
|
+
@features.merge(arg)
|
95
|
+
else
|
96
|
+
@features[arg] = true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
protected
|
101
|
+
def theme_home(kaller)
|
102
|
+
if kaller[0] =~ /^(.+?):(\d+)(?::in `(.*)')?/
|
103
|
+
File.dirname($1)
|
104
|
+
else
|
105
|
+
raise "WTF: #{kaller.inspect}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def theme_version
|
110
|
+
version_file = File.join(@home, "VERSION")
|
111
|
+
unless File.exists?(version_file)
|
112
|
+
raise "No VERSION file in #{@home}, create it or set a version"
|
113
|
+
end
|
114
|
+
|
115
|
+
version = File.read(version_file).strip
|
116
|
+
puts "base version: #{version}" if @verbose
|
117
|
+
|
118
|
+
if build_number = ENV['BUILD_NUMBER']
|
119
|
+
puts "build: #{build_number}" if @verbose
|
120
|
+
version << "-" + build_number
|
121
|
+
end
|
122
|
+
|
123
|
+
puts "version: #{version}" if @verbose
|
124
|
+
version
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
data/lib/savory/theme.rb
ADDED
data/lib/savory_theme.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'savory/theme'
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: savory_theme
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 1.0.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrea Campi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-05-30 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rubyzip
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.9.8
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
description: Savory theme support
|
27
|
+
email:
|
28
|
+
- andrea.campi@zephirworks.com
|
29
|
+
executables:
|
30
|
+
- savory-theme
|
31
|
+
extensions: []
|
32
|
+
|
33
|
+
extra_rdoc_files:
|
34
|
+
- LICENSE
|
35
|
+
- README.md
|
36
|
+
files:
|
37
|
+
- bin/savory-theme
|
38
|
+
- lib/savory/theme/bom.rb
|
39
|
+
- lib/savory/theme/exec.rb
|
40
|
+
- lib/savory/theme/layout/legacy.rb
|
41
|
+
- lib/savory/theme/layout/treesaver.rb
|
42
|
+
- lib/savory/theme/layout.rb
|
43
|
+
- lib/savory/theme/packager/features/compass.rb
|
44
|
+
- lib/savory/theme/packager/features/sass.rb
|
45
|
+
- lib/savory/theme/packager/features.rb
|
46
|
+
- lib/savory/theme/packager.rb
|
47
|
+
- lib/savory/theme/theme_task.rb
|
48
|
+
- lib/savory/theme/version.rb
|
49
|
+
- lib/savory/theme.rb
|
50
|
+
- lib/savory_theme.rb
|
51
|
+
- files/app/views/pages/404.liquid
|
52
|
+
- files/app/views/pages/articles/content_type_template.liquid
|
53
|
+
- files/app/views/pages/articles.liquid
|
54
|
+
- files/app/views/pages/contents.liquid
|
55
|
+
- files/app/views/pages/cover.liquid
|
56
|
+
- files/app/views/pages/index.liquid
|
57
|
+
- files/app/views/pages/layout.liquid
|
58
|
+
- files/app/views/pages/resources.liquid
|
59
|
+
- files/app/views/templates/figure.html
|
60
|
+
- files/config/compiled_site.yml
|
61
|
+
- files/config/locales/en.yml
|
62
|
+
- files/config/theme_config.yml
|
63
|
+
- files/data/articles.yml
|
64
|
+
- files/data/covers.yml
|
65
|
+
- files/Rakefile.erb
|
66
|
+
- LICENSE
|
67
|
+
- README.md
|
68
|
+
homepage: http://savory.io
|
69
|
+
licenses: []
|
70
|
+
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: "0"
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 1.3.6
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project: nowarning
|
91
|
+
rubygems_version: 1.8.10
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: Savory theme support
|
95
|
+
test_files: []
|
96
|
+
|
97
|
+
has_rdoc:
|