homeostasis 0.0.9 → 0.0.10

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.
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)