homeostasis 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  Description
2
2
  ===========
3
3
 
4
- Stasis plugin for asset stamping, blogs, front-matter yaml, and trailing
5
- slashes.
4
+ Stasis plugin for asset stamping, blogs, front-matter yaml, sitemaps, and
5
+ trailing slashes.
6
6
 
7
7
  Installation
8
8
  ============
@@ -35,13 +35,16 @@ You'll end up with something like this:
35
35
  styles.sha1.css
36
36
 
37
37
  Generated files in the `public` directory will go through a global search and
38
- replace.
38
+ replace. By default, it'll only do this on `html`, `css`, and `js` files.
39
+ You can configure this:
40
+
41
+ Homeostasis::Asset.replace_matcher = /.(html|css|js)$/i
39
42
 
40
43
  You can set the regex for asset matching in your controller:
41
44
 
42
45
  Homeostasis::Asset.matcher = /myregex$/i
43
46
 
44
- You can even concat your assets into a single file:
47
+ You can also configure concatenation of multiple assets into a single file:
45
48
 
46
49
  Homeostasis::Asset.concat 'all.js', %w(jquery.js mine.js)
47
50
  Homeostasis::Asset.concat 'all.css', %w(reset.css mine.css)
@@ -106,6 +109,14 @@ cross-page access.
106
109
  Note that `:path` is automatically assigned if left blank. Its value will be
107
110
  the public path to the page.
108
111
 
112
+ Sitemap
113
+ =======
114
+
115
+ A sitemap will automatically be generated in `public/sitemap.xml`. You'll need
116
+ to set the root URL for this to happen:
117
+
118
+ Homeostasis.root 'http://example.com'
119
+
109
120
  Trailing Slash
110
121
  ==============
111
122
 
@@ -125,6 +136,14 @@ You'll get:
125
136
  This works well with an `htaccess` file that automatically appends trailing
126
137
  slashes to URLs.
127
138
 
139
+ TODO
140
+ ====
141
+
142
+ * use Dir.glob with relative paths
143
+ * add tests/coverage
144
+ * RSS generation
145
+ * sitemap generation
146
+
128
147
  License
129
148
  =======
130
149
 
data/lib/homeostasis.rb CHANGED
@@ -1,10 +1,284 @@
1
+ require 'rubygems'
2
+ require 'stasis'
3
+ require 'digest/sha1'
4
+ require 'yaml'
5
+
1
6
  module Homeostasis
2
- VERSION = '0.0.9'
7
+ VERSION = '0.0.10'
8
+
9
+ class Asset < Stasis::Plugin
10
+ before_all :before_all
11
+ after_all :after_all
12
+
13
+ def initialize(stasis)
14
+ @stasis = stasis
15
+ @@matcher = /\.(jpg|png|gif|css|js)/i
16
+ @@replace_matcher = /\.(html|css|js)/i
17
+ @@mapping = {}
18
+ @@concats = {}
19
+ @@orig_concats = {}
20
+ end
21
+
22
+ def before_all
23
+ # build mapping of relative filenames => destination
24
+ @stasis.paths.each do |path|
25
+ next if ignore?(path)
26
+ relative = path[(@stasis.root.length+1)..-1]
27
+ ext = Tilt.mappings.keys.find { |ext| File.extname(path)[1..-1] == ext }
28
+ dest = (ext && File.extname(relative) == ".#{ext}") ?
29
+ relative[0..-1*ext.length-2] :
30
+ relative
31
+ @@mapping[relative] = dest
32
+ end
33
+
34
+ # build orig_concats of destination => [original filenames,]
35
+ inverted = @@mapping.invert
36
+ @@concats.each do |dest, files|
37
+ @@orig_concats[dest] = files.map do |file|
38
+ raise "Asset not found #{file}" if !inverted.has_key?(file)
39
+ File.join(@stasis.root, inverted[file])
40
+ end
41
+ end
42
+ end
43
+
44
+ def after_all
45
+ assets = {}
46
+ strip_dest = (@stasis.destination.length + 1)..-1
47
+ strip_root = (@stasis.root.length + 1)..-1
48
+
49
+ # concatenate files with stamps
50
+ @@orig_concats.each do |concatted, files|
51
+ full_concatted = self.class.stamped(
52
+ File.join(@stasis.destination, concatted),
53
+ self.class.version(files))
54
+ content = files.map do |full_orig|
55
+ orig = full_orig[(@stasis.root.length+1)..-1]
56
+ full_dest = File.join(@stasis.destination, @@mapping[orig])
57
+ raise "File not found #{full_dest}" if !File.exists?(full_dest)
58
+ contents = File.read(full_dest)
59
+ @@mapping.delete(orig)
60
+ File.delete(full_dest)
61
+ contents
62
+ end.join("\n")
63
+ File.open(full_concatted, 'w') { |f| f.print(content) }
64
+ assets[concatted] = full_concatted[strip_dest]
65
+ end
66
+
67
+ # stamp files that don't require concatentation
68
+ @@mapping.each do |orig, dest|
69
+ next if dest !~ @@matcher
70
+ full_orig = File.join(@stasis.root, orig)
71
+ full_dest = File.join(@stasis.destination, dest)
72
+ versioned = self.class.stamped(full_dest, self.class.version(full_orig))
73
+ File.rename(full_dest, versioned)
74
+ assets[full_dest[strip_dest]] = versioned[strip_dest]
75
+ end
76
+
77
+ # read contents of each file, search/replace assets with stamps
78
+ Dir.glob("#{@stasis.destination[strip_root]}/**/*").each do |file|
79
+ next if file !~ @@replace_matcher || File.directory?(file)
80
+ contents = File.read(file)
81
+ assets.each do |old, new|
82
+ old = Regexp.escape(old)
83
+ contents.gsub!(/([^a-zA-Z0-9\.\-_])#{old}/, "\\1#{new}")
84
+ contents.gsub!(/^#{old}/, new)
85
+ end
86
+ File.open(file, 'w') { |f| f.print(contents) }
87
+ end
88
+ end
89
+
90
+ def self.stamped(path, version)
91
+ path = path.split('.')
92
+ path.insert(path.length > 1 ? -2 : -1, version)
93
+ path.join('.')
94
+ end
95
+
96
+ def self.version(paths)
97
+ paths = [paths] if !paths.is_a?(Array)
98
+ versions = paths.map do |path|
99
+ log = `git log -n1 #{path} 2> /dev/null`.split("\n")
100
+ log.length > 1 ? log[0].split(' ').last : '0'
101
+ end
102
+ versions.size == 1 ?
103
+ versions[0] :
104
+ Digest::SHA1.hexdigest(versions.join('.'))
105
+ end
106
+
107
+ def self.matcher=(regex)
108
+ @@matcher = regex
109
+ end
110
+
111
+ def self.replace_matcher=(regex)
112
+ @@replace_matcher = regex
113
+ end
114
+
115
+ def self.concat(dest, files)
116
+ @@concats[dest] = files
117
+ end
118
+
119
+ private
120
+ def ignore?(path)
121
+ @ignore_paths ||= @stasis.plugins.
122
+ find { |plugin| plugin.class == Stasis::Ignore }.
123
+ instance_variable_get(:@ignore)
124
+
125
+ matches = _match_key?(@ignore_paths, path)
126
+ matches.each do |group|
127
+ group.each do |group_path|
128
+ return true if _within?(group_path)
129
+ end
130
+ end
131
+ false
132
+ end
133
+ end
134
+
135
+ class Front < Stasis::Plugin
136
+ before_all :before_all
137
+ action_method :front
138
+ action_method :front_site
139
+
140
+ def initialize(stasis)
141
+ @stasis = stasis
142
+ @@front_site = {}
143
+ @@matchers = {
144
+ 'erb' => /<%#/,
145
+ 'haml' => /-#/,
146
+ 'html' => /<!--/,
147
+ 'md' => /<!--/
148
+ }
149
+ end
150
+
151
+ def before_all
152
+ @stasis.paths.each do |path|
153
+ next if path !~ /\.(#{@@matchers.keys.join('|')})$/
154
+ next if (contents = File.read(path)) !~ @@matchers[File.extname(path)[1..-1]]
155
+
156
+ lines, data, index = contents.split("\n"), "", 1
157
+ while index < lines.size
158
+ break if lines[index] !~ /^ /
159
+ data += lines[index] + "\n"
160
+ index += 1
161
+ end
162
+
163
+ relative = path[(@stasis.root.length+1)..-1]
164
+ ext = Tilt.mappings.keys.find { |ext| File.extname(path)[1..-1] == ext }
165
+ dest = trailify((ext && File.extname(relative) == ".#{ext}") ?
166
+ relative[0..-1*ext.length-2] :
167
+ relative)
168
+
169
+ begin
170
+ yaml = YAML.load(data)
171
+ yaml[:path] = dest
172
+ @@front_site[front_key(path)] = yaml if yaml.is_a?(Hash)
173
+ rescue Psych::SyntaxError => error
174
+ @@front_site[front_key(path)] = {:path => dest}
175
+ end
176
+ end
177
+ end
178
+
179
+ def front
180
+ @@front_site[front_key(@stasis.path)] || {}
181
+ end
182
+
183
+ def front_site
184
+ @@front_site
185
+ end
186
+
187
+ def self._front_site # for other plugins
188
+ @@front_site
189
+ end
190
+
191
+ def self.matchers=(ext)
192
+ @@matchers = ext
193
+ end
194
+
195
+ private
196
+ def front_key(filename)
197
+ filename.sub(@stasis.root, '')[1..-1]
198
+ end
199
+
200
+ def trailify(filename)
201
+ @trail_included ||= @stasis.plugins.any? { |plugin| plugin.is_a?(Homeostasis::Trail) }
202
+ if filename == 'index.html'
203
+ '/'
204
+ elsif File.basename(filename) == 'index.html'
205
+ "/#{File.dirname(filename)}/"
206
+ elsif @trail_included
207
+ "/#{filename.sub(/\.html$/, '/')}"
208
+ else
209
+ "/#{filename}"
210
+ end
211
+ end
212
+ end
213
+
214
+ class Trail < Stasis::Plugin
215
+ after_all :after_all
216
+
217
+ def initialize(stasis)
218
+ @stasis = stasis
219
+ end
220
+
221
+ def after_all
222
+ dest = @stasis.destination[(@stasis.root.length + 1)..-1]
223
+ Dir.glob("#{dest}/**/*.html").each do |filename|
224
+ next if filename =~ /\/index\.html$/
225
+ dir = "#{filename.sub(/\.html$/, '')}/"
226
+ FileUtils.mkdir_p(dir)
227
+ File.rename(filename, "#{dir}index.html")
228
+ end
229
+ end
230
+ end
231
+
232
+ class Blog < Stasis::Plugin
233
+ DATE_REGEX = /^(\d{4}-\d{2}-\d{2})-/
234
+ before_all :before_all
235
+ after_all :after_all
236
+ action_method :blog_posts
237
+
238
+ def initialize(stasis)
239
+ @stasis = stasis
240
+ @@directory = nil
241
+ @@posts = []
242
+ end
243
+
244
+ def self.directory(directory)
245
+ @@directory = directory
246
+ end
247
+
248
+ def before_all
249
+ return if @@directory.nil?
250
+ front_site = Homeostasis::Front._front_site
251
+ Dir.glob("#{File.join(@stasis.root, @@directory)}/*").each do |filename|
252
+ next if File.basename(filename) !~ DATE_REGEX
253
+ date = $1
254
+ post = front_site[filename.sub(@stasis.root, '')[1..-1]] || {}
255
+ post[:date] = Date.parse(date)
256
+ post[:path] = post[:path].sub("/#{@@directory}/#{date}-", "/#{@@directory}/")
257
+ @@posts << post
258
+ end
259
+ @@posts = @@posts.sort_by { |post| post[:date] }.reverse
260
+ end
261
+
262
+ def after_all
263
+ return if @@directory.nil?
264
+ Dir.glob("#{File.join(@stasis.destination, @@directory)}/*").each do |filename|
265
+ next if (base = File.basename(filename)) !~ DATE_REGEX
266
+ FileUtils.mv(
267
+ filename,
268
+ File.join(File.dirname(filename), base.sub(DATE_REGEX, '')))
269
+ end
270
+ end
271
+
272
+ def blog_posts
273
+ raise 'Homeostasis::Blog#directory never set' if @@directory.nil?
274
+ @@posts
275
+ end
276
+ end
3
277
  end
4
278
 
5
- if !ENV['HOMEOSTASIS_BUILD']
6
- require File.join(File.dirname(__FILE__), 'homeostasis', 'asset')
7
- require File.join(File.dirname(__FILE__), 'homeostasis', 'front')
8
- require File.join(File.dirname(__FILE__), 'homeostasis', 'trail')
9
- require File.join(File.dirname(__FILE__), 'homeostasis', 'blog')
279
+ if !ENV['HOMEOSTASIS_UNREGISTER']
280
+ Stasis.register(Homeostasis::Asset)
281
+ Stasis.register(Homeostasis::Front)
282
+ Stasis.register(Homeostasis::Trail)
283
+ Stasis.register(Homeostasis::Blog)
10
284
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: homeostasis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.0.10
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-03 00:00:00.000000000 Z
12
+ date: 2012-08-06 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Provides asset stamping using git revisions, environments, and a few
15
15
  view helpers.
@@ -21,10 +21,6 @@ extra_rdoc_files: []
21
21
  files:
22
22
  - LICENSE.md
23
23
  - README.md
24
- - lib/homeostasis/trail.rb
25
- - lib/homeostasis/blog.rb
26
- - lib/homeostasis/front.rb
27
- - lib/homeostasis/asset.rb
28
24
  - lib/homeostasis.rb
29
25
  homepage: https://github.com/hughbien/homeostasis
30
26
  licenses: []
@@ -1,133 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', 'homeostasis')
2
- require 'digest/sha1'
3
-
4
- class Homeostasis::Asset < Stasis::Plugin
5
- before_all :before_all
6
- after_all :after_all
7
-
8
- def initialize(stasis)
9
- @stasis = stasis
10
- @@matcher = /\.(jpg|png|gif|css|js)/i
11
- @@mapping = {}
12
- @@concats = {}
13
- @@concats_pre = {}
14
- end
15
-
16
- def before_all
17
- @stasis.paths.each do |path|
18
- next if ignore?(path)
19
- relative = path[(@stasis.root.length+1)..-1]
20
- ext = Tilt.mappings.keys.find { |ext| File.extname(path)[1..-1] == ext }
21
- dest = (ext && File.extname(relative) == ".#{ext}") ?
22
- relative[0..-1*ext.length-2] :
23
- relative
24
- @@mapping[relative] = dest
25
- end
26
- imapping = @@mapping.invert
27
- @@concats_pre.each do |dest, files|
28
- full_origs = files.map do |file|
29
- orig = imapping[file]
30
- raise "Asset not found #{file}" if orig.nil?
31
- File.join(@stasis.root, imapping[file])
32
- end
33
- @@concats[dest] = full_origs
34
- end
35
- end
36
-
37
- def after_all
38
- asset_paths = {}
39
- @@concats.each do |concatted, files|
40
- version = self.class.version(files)
41
- full_concatted = File.join(@stasis.destination, concatted)
42
- full_concatted = self.class.stamped(full_concatted, version)
43
- content = files.map do |full_orig|
44
- orig = full_orig[(@stasis.root.length+1)..-1]
45
- full_dest = File.join(@stasis.destination, @@mapping[orig])
46
- raise "File not found #{full_dest}" if !File.exists?(full_dest)
47
- file_contents = File.read(full_dest)
48
- @@mapping.delete(orig)
49
- File.delete(full_dest)
50
- file_contents
51
- end.join("\n")
52
- File.open(full_concatted, 'w') {|f| f.print(content)}
53
- asset_paths[concatted] = full_concatted[(@stasis.destination.length+1)..-1]
54
- end
55
- @@mapping.each do |orig, dest|
56
- next if dest !~ @@matcher
57
- full_orig = File.join(@stasis.root, orig)
58
- full_dest = File.join(@stasis.destination, dest)
59
- versioned = self.class.stamped(full_dest, self.class.version(full_orig))
60
- File.rename(full_dest, versioned)
61
-
62
- relative_dest = full_dest[(@stasis.destination.length+1)..-1]
63
- relative_versioned = versioned[(@stasis.destination.length+1)..-1]
64
- asset_paths[relative_dest] = relative_versioned
65
- end
66
- (@@mapping.values + asset_paths.values).each do |dest|
67
- filename = File.join(@stasis.destination, dest)
68
- next if !File.exist?(filename)
69
- contents = File.read(filename)
70
- begin
71
- asset_paths.each do |old, new|
72
- contents.gsub!(/([^a-zA-Z0-9\.\-_])#{Regexp.escape(old)}/, "\\1#{new}")
73
- contents.gsub!(/^#{Regexp.escape(old)}/, new)
74
- end
75
- File.open(filename, 'w') {|f| f.print(contents)}
76
- rescue ArgumentError
77
- next
78
- end
79
- end
80
- end
81
-
82
- def self.stamped(path, version)
83
- path = path.split('.')
84
- path.insert(
85
- path.length > 1 ? -2 : -1,
86
- version)
87
- path.join('.')
88
- end
89
-
90
- def self.version(paths)
91
- paths = [paths] if !paths.is_a?(Array)
92
- versions = paths.map do |path|
93
- log = `git log -n1 #{path} 2> /dev/null`.split("\n")
94
- log.length > 1 ? log[0].split(' ').last : '0'
95
- end
96
- versions.size == 1 ?
97
- versions[0] :
98
- Digest::SHA1.hexdigest(versions.join('.'))
99
- end
100
-
101
- def self.matcher=(regex)
102
- @@matcher = regex
103
- end
104
-
105
- def self.mapping
106
- @@mapping
107
- end
108
-
109
- def self.concat(dest, files)
110
- @@concats_pre[dest] = files
111
- end
112
-
113
- def self.concats
114
- @@concats
115
- end
116
-
117
- private
118
- def ignore?(path)
119
- @ignore_paths ||= @stasis.plugins.
120
- find { |plugin| plugin.class == Stasis::Ignore }.
121
- instance_variable_get(:@ignore)
122
-
123
- matches = _match_key?(@ignore_paths, path)
124
- matches.each do |group|
125
- group.each do |group_path|
126
- return true if _within?(group_path)
127
- end
128
- end
129
- false
130
- end
131
- end
132
-
133
- Stasis.register(Homeostasis::Asset)
@@ -1,50 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', 'homeostasis')
2
- require 'date'
3
-
4
- class Homeostasis::Blog < Stasis::Plugin
5
- before_all :before_all
6
- after_all :after_all
7
- action_method :blog_posts
8
-
9
- def initialize(stasis)
10
- @stasis = stasis
11
- @@directory = nil
12
- @@posts = []
13
- end
14
-
15
- def self.directory(directory)
16
- @@directory = directory
17
- end
18
-
19
- def before_all
20
- raise 'Homeostasis::Blog#directory never set' if @@directory.nil?
21
- blog_dir = File.join(@stasis.root, @@directory)
22
- front_site = Homeostasis::Front._front_site
23
- Dir.glob("#{blog_dir}/*").each do |filename|
24
- next if File.basename(filename) !~ /^(\d{4}-\d{2}-\d{2})-/
25
- date = $1
26
- post = front_site[filename.sub(@stasis.root, '')[1..-1]] || {}
27
- post[:date] = Date.parse(date)
28
- post[:path] = post[:path].sub("/#{@@directory}/#{$1}-", "/#{@@directory}/")
29
- @@posts << post
30
- end
31
- @@posts = @@posts.sort_by {|post| post[:date]}.reverse
32
- end
33
-
34
- def after_all
35
- return if @@directory.nil?
36
- blog_dir = File.join(@stasis.destination, @@directory)
37
- Dir.glob("#{blog_dir}/*").each do |filename|
38
- next if filename !~ /^\d{4}-\d{2}-\d{2}-/
39
- newbase = File.basename(filename).sub(/^(\d{4}-\d{2}-\d{2})-/, '')
40
- FileUtils.mv(filename, File.join(File.dirname(filename), newbase))
41
- end
42
- end
43
-
44
- def blog_posts
45
- raise 'Homeostasis::Blog#directory never set' if @@directory.nil?
46
- @@posts
47
- end
48
- end
49
-
50
- Stasis.register(Homeostasis::Blog)
@@ -1,89 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', 'homeostasis')
2
- require 'yaml'
3
-
4
- class Homeostasis::Front < Stasis::Plugin
5
- before_all :before_all
6
- action_method :front
7
- action_method :front_site
8
-
9
- def initialize(stasis)
10
- @stasis = stasis
11
- @@front_site = {}
12
- @@matchers = {
13
- 'erb' => /<%#/,
14
- 'haml' => /-#/,
15
- 'html' => /<!--/,
16
- 'md' => /<!--/
17
- }
18
- end
19
-
20
- def before_all
21
- @stasis.paths.each do |path|
22
- next if path !~ /\.(#{@@matchers.keys.join('|')})$/
23
- contents = File.read(path)
24
- next if contents !~ @@matchers[File.extname(path)[1..-1]]
25
-
26
- lines, data, index = contents.split("\n"), "", 1
27
- while index < lines.size
28
- break if lines[index] !~ /^ /
29
- data += lines[index] + "\n"
30
- index += 1
31
- end
32
-
33
- relative = path[(@stasis.root.length+1)..-1]
34
- ext = Tilt.mappings.keys.find { |ext| File.extname(path)[1..-1] == ext }
35
- dest = (ext && File.extname(relative) == ".#{ext}") ?
36
- relative[0..-1*ext.length-2] :
37
- relative
38
- dest = trailify(dest)
39
-
40
- begin
41
- yaml = YAML.load(data)
42
- yaml[:path] = dest
43
- @@front_site[front_key(path)] = yaml if yaml.is_a?(Hash)
44
- rescue Psych::SyntaxError => error
45
- @@front_site[front_key(path)] = {:path => dest}
46
- end
47
- end
48
- end
49
-
50
- def front
51
- @@front_site[front_key(@stasis.path)] || {}
52
- end
53
-
54
- def front_site
55
- @@front_site
56
- end
57
-
58
- def self._front_site # for other plugins
59
- @@front_site
60
- end
61
-
62
- def self.matchers
63
- @@matchers
64
- end
65
-
66
- def self.matchers=(ext)
67
- @@matchers = ext
68
- end
69
-
70
- private
71
- def front_key(filename)
72
- filename.sub(@stasis.root, '')[1..-1]
73
- end
74
-
75
- def trailify(filename)
76
- @trail_included ||= @stasis.plugins.any? {|plugin| plugin.is_a?(Homeostasis::Trail)}
77
- if filename == 'index.html'
78
- '/'
79
- elsif File.basename(filename) == 'index.html'
80
- "/#{File.dirname(filename)}/"
81
- elsif @trail_included
82
- "/#{filename.sub(/\.html$/, '/')}"
83
- else
84
- "/#{filename}"
85
- end
86
- end
87
- end
88
-
89
- Stasis.register(Homeostasis::Front)
@@ -1,24 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', 'homeostasis')
2
-
3
- class Homeostasis::Trail < Stasis::Plugin
4
- after_all :after_all
5
-
6
- def initialize(stasis)
7
- @stasis = stasis
8
- end
9
-
10
- def after_all
11
- Dir.glob("#{@stasis.destination}/**/*.html").each do |filename|
12
- next if File.basename(filename) == 'index.html'
13
- dir = "#{filename[0..-6]}/"
14
- if File.exists?("#{dir}index.html")
15
- puts "Unable to trail #{filename[(@stasis.destination.length+1)..-1]}"
16
- else
17
- FileUtils.mkdir_p(dir)
18
- File.rename(filename, "#{dir}index.html")
19
- end
20
- end
21
- end
22
- end
23
-
24
- Stasis.register(Homeostasis::Trail)