-
Notifications
You must be signed in to change notification settings - Fork 0
/
theme.rb
154 lines (134 loc) · 4.87 KB
/
theme.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
class Theme
@@root_theme_files = %w(about.yml preview.png)
@@theme_directories = %w(templates layouts javascripts stylesheets images)
@@allowed_extensions = %w(.js .css .png .gif .jpg .swf .ico) | Site.extensions
cattr_reader :root_theme_files, :theme_directories, :allowed_extensions
attr_reader :path, :base_path, :extension
def self.import(zip_file, options = {})
dest = options[:to].is_a?(Pathname) ? options[:to] : Pathname.new(options[:to] || '.')
basename = dest.basename.to_s
if dest.exist? || basename == 'current'
basename = basename =~ /(.*)_(\d+)\z/ ? $1 : basename
number = $2 ? $2.to_i + 1 : 2
dirname = dest.dirname
dest = dirname + "#{basename}_#{number}"
while dest.exist?
number += 1
dest = dirname + "#{basename}_#{number}"
end
end
FileUtils.mkdir_p dest.to_s unless dest.exist?
Zip::ZipFile.open(zip_file) do |z|
root_theme_files.each do |file|
z.file.open(file) { |zf| File.open(dest + file, 'wb') { |f| f << zf.read } } if z.file.exist?(file)
end
theme_directories.each do |dir|
dir_path = Pathname.new(dest + dir)
FileUtils.mkdir_p dir_path unless dir_path.exist?
z.dir.entries(dir).each do |entry|
next unless entry =~ /(\.\w+)\z/ && allowed_extensions.include?($1)
z.file.open(File.join(dir, entry)) { |zf| File.open(dir_path + entry, 'wb') { |f| f << zf.read } }
end
end
end
dest.basename.to_s
rescue
dest.rmtree if dest.exist?
raise ThemeError.new(dest, $!.message)
end
def initialize(base, site = nil)
@site = site
if base.is_a?(Pathname)
@base_path = base.to_s
@path = base
else
@base_path = base
@path = Pathname.new(@base_path)
end
layout = (@path + "layouts").children(false).select {|v| v.to_s =~ /\Alayout/}[0] if (@path + "layouts").directory?
@extension = layout.extname if layout
end
def current?
@current ||= (@site && @site.current_theme_path == @path.basename.to_s) || :false
@current != :false
end
def name
class << self ; attr_reader :name ; end
@name = @path.basename.to_s
end
alias to_param name
def preview
class << self; attr_reader :preview ; end
@preview = @path + 'preview.png'
end
def properties
class << self ; attr_reader :properties ; end
about = path + 'about.yml'
@properties = about.exist? ? YAML.load_file(about) : {}
end
[:summary, :author, :version, :homepage].each do |attr_name|
eval <<-END
def #{attr_name}
class << self ; attr_reader :#{attr_name} ; end
@#{attr_name} = properties['#{attr_name}']
end
END
end
def title
class << self ; attr_reader :title ; end
@title = properties['title'] || name
end
def attachments
class << self ; attr_reader :attachments ; end
@attachments, @templates, @resources = Attachments.new, Templates.new, Resources.new
[@attachments, @templates, @resources].each { |a| a.theme = self }
Pathname.glob(File.join(base_path, '*/*')).each do |path|
next unless path.file?
@attachments << path
((path.extname == @extension) ? @templates : @resources) << path
end
@attachments
end
def resources
class << self ; attr_reader :resources ; end
attachments && instance_variable_get(:@resources)
end
def templates
class << self ; attr_reader :templates ; end
attachments && instance_variable_get(:@templates)
end
def export_as_zip(name, options = {})
path = options[:to] || '.'
Zip::ZipFile.open(File.join(path, "#{name}.zip"), Zip::ZipFile::CREATE) do |zip|
theme_directories.each { |d| zip.dir.mkdir(d) }
write_theme_files_with zip.file
end
end
def export(name, options = {})
path = File.join(options[:to] || '.', name)
theme_directories.each { |d| FileUtils.mkdir_p File.join(path, d) }
write_theme_files_with File, path
end
def eql?(comparison_object)
self == (comparison_object)
end
def ==(comparison_object)
base_path == (comparison_object.is_a?(Theme) ? comparison_object.base_path : comparison_object.to_s)
end
def similar_to?(theme)
title == theme.title && version == theme.version
end
protected
def write_theme_files_with(file_class, relative_path = '')
# ZipFileSystem doesn't support wb
write_mode = file_class.is_a?(Zip::ZipFileSystem::ZipFsFile) ? 'w' : 'wb'
relative_path = Pathname.new(relative_path) unless relative_path.is_a?(Pathname)
root_theme_files.each do |file|
real_file = path + file
file_class.open((relative_path + file).to_s, write_mode) { |f| f << real_file.read } if real_file.exist?
end
attachments.each do |full_path|
file_class.open((relative_path + full_path.relative_path_from(path)).to_s, write_mode) { |f| f << full_path.read }
end
end
end