spontaneous 0.2.0.beta7 → 0.2.0.beta8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/application/css/core.css.scss +4 -4
- data/application/css/definitions.css.scss +6 -1
- data/application/css/dialogue.css.scss +1 -0
- data/application/js/field/file.js +18 -3
- data/application/js/field/image.js +2 -5
- data/db/migrations/20140514090204_add_content_hash.rb +33 -22
- data/db/migrations/20140519150253_add_content_hash_timestamp.rb +14 -3
- data/lib/spontaneous/asset/environment.rb +20 -22
- data/lib/spontaneous/model/core.rb +12 -1
- data/lib/spontaneous/model/page/paths.rb +5 -11
- data/lib/spontaneous/page_piece.rb +6 -0
- data/lib/spontaneous/publishing/steps.rb +2 -0
- data/lib/spontaneous/publishing/steps/copy_assets.rb +77 -0
- data/lib/spontaneous/version.rb +1 -1
- data/test/fixtures/example_application/assets/css/site.css.scss +6 -0
- data/test/fixtures/example_application/assets/i/sine_waves.png +0 -0
- data/test/fixtures/example_application/assets/i/xes.png +0 -0
- data/test/functional/test_back.rb +1 -1
- data/test/unit/test_asset_bundler.rb +6 -6
- data/test/unit/test_assets.rb +85 -49
- data/test/unit/test_content.rb +10 -0
- data/test/unit/test_publishing_pipeline.rb +74 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1fbce2b0e756da55c854fb535ed8454a1aed9aed
|
4
|
+
data.tar.gz: 9a3d4faf5726570997d13c3786246768c3c3495e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71decdd38247bc06e094eec89575a899b8e95a4156f4a8b431548b58a591f3721ee585b134a420faa773beed01be88c9ca70470db1d425d61bd5fdba8d7167d3
|
7
|
+
data.tar.gz: 08ddbb0a24ccf19d7b2a76ab72e0d677ade2106d259deb00a3c9884aaa84454ac1073ee29d56eebc78fdca3e4886898c1477f792deb49ad66e5dffb7b823bd42
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 0.2.0.beta8, released 2014-10-29
|
2
|
+
|
3
|
+
#### Fixes
|
4
|
+
|
5
|
+
- Include `-webkit` prefixed versions of all flexbox properties to fix display in Safari
|
6
|
+
- Fix image drag & drop in Chrome -- revoking blob URLs immediately now results in a broken image
|
7
|
+
- Remove all references to `Page#path` in initialization to avoid trying to resolve the full path before the pages' parents have been assigned
|
8
|
+
- Explicitly copy compiled assets to the new published revision using a new core publish step rather than hijack the asset compilation/resolution step. This ensures that dependencies are copied on a second publish.
|
9
|
+
- Fix layout of box tabs by using appropriate mixins to apply `-webkit` prefixed styles
|
10
|
+
|
1
11
|
## 0.2.0.beta7, released 2014-09-03
|
2
12
|
|
3
13
|
#### Fixes
|
@@ -659,17 +659,17 @@
|
|
659
659
|
height: 100%;
|
660
660
|
|
661
661
|
.slot-tabs {
|
662
|
+
@include display-box;
|
663
|
+
@include box-orient(row);
|
662
664
|
min-height: 32px;
|
663
665
|
vertical-align: top;
|
664
666
|
@include vertical-gradient(#666666, #4d4d4d);
|
665
667
|
padding-left: $container-padding;
|
666
668
|
padding-right: $container-padding;
|
667
|
-
display: flex;
|
668
|
-
flex-direction: row;
|
669
669
|
li {
|
670
670
|
@include box-sizing;
|
671
671
|
@include interface;
|
672
|
-
flex
|
672
|
+
@include box-flex(1);
|
673
673
|
font-size: 11px;
|
674
674
|
color: #dddddd;
|
675
675
|
display: block;
|
@@ -1669,7 +1669,7 @@
|
|
1669
1669
|
|
1670
1670
|
@media all and (max-width: 1000px) {
|
1671
1671
|
.fields-preview-text li {
|
1672
|
-
|
1672
|
+
@include box-orient(column);
|
1673
1673
|
}
|
1674
1674
|
}
|
1675
1675
|
@import "top.css.scss";
|
@@ -115,6 +115,7 @@ $target-name-size: 14px;
|
|
115
115
|
// display: -webkit-box;
|
116
116
|
// display: -moz-box;
|
117
117
|
display: flex;
|
118
|
+
display: -webkit-flex;
|
118
119
|
}
|
119
120
|
@mixin box-sizing($model: border-box) {
|
120
121
|
-webkit-box-sizing: $model;
|
@@ -124,15 +125,19 @@ $target-name-size: 14px;
|
|
124
125
|
|
125
126
|
@mixin box-orient($direction: row) {
|
126
127
|
flex-direction: $direction;
|
128
|
+
-webkit-flex-direction: $direction;
|
127
129
|
}
|
128
130
|
@mixin box-pack($packing: center) {
|
129
131
|
justify-content: $packing;
|
132
|
+
-webkit-justify-content: $packing;
|
130
133
|
}
|
131
134
|
@mixin box-align($aligning: start) {
|
132
135
|
align-items: $aligning;
|
136
|
+
-webkit-align-items: $aligning;
|
133
137
|
}
|
134
138
|
@mixin box-flex($flex: 1) {
|
135
|
-
|
139
|
+
flex-grow: $flex;
|
140
|
+
-webkit-flex-grow: $flex;
|
136
141
|
}
|
137
142
|
|
138
143
|
@mixin no-select {
|
@@ -4,6 +4,10 @@ Spontaneous.Field.File = (function($, S) {
|
|
4
4
|
var FileField = new JS.Class(Spontaneous.Field.String, {
|
5
5
|
selected_files: false,
|
6
6
|
|
7
|
+
initialize: function(dialogue, conflict) {
|
8
|
+
this.blobs = [];
|
9
|
+
this.callSuper();
|
10
|
+
},
|
7
11
|
currentValue: function() {
|
8
12
|
var pending, v = this.get('value');
|
9
13
|
if ((pending = v.__pending__)) {
|
@@ -111,10 +115,16 @@ Spontaneous.Field.File = (function($, S) {
|
|
111
115
|
dialogue.open();
|
112
116
|
},
|
113
117
|
unload: function() {
|
114
|
-
this.callSuper();
|
115
118
|
this.input = null;
|
116
119
|
this._progress_bar = null;
|
120
|
+
this.freeBlobs();
|
117
121
|
Spontaneous.UploadManager.unregister(this);
|
122
|
+
this.callSuper();
|
123
|
+
},
|
124
|
+
freeBlobs: function() {
|
125
|
+
this.blobs.forEach(function(url) {
|
126
|
+
window.URL.revokeObjectURL(url);
|
127
|
+
});
|
118
128
|
},
|
119
129
|
upload_complete: function(values) {
|
120
130
|
this.set('value', values.processed_value);
|
@@ -146,6 +156,12 @@ Spontaneous.Field.File = (function($, S) {
|
|
146
156
|
return true;
|
147
157
|
},
|
148
158
|
|
159
|
+
createObjectURL: function(file) {
|
160
|
+
var url = window.URL.createObjectURL(file);
|
161
|
+
this.blobs.push(url);
|
162
|
+
return url;
|
163
|
+
},
|
164
|
+
|
149
165
|
edit: function() {
|
150
166
|
var self = this;
|
151
167
|
var wrap = dom.div('.file-field', {'style':'position:relative;'});
|
@@ -164,10 +180,9 @@ Spontaneous.Field.File = (function($, S) {
|
|
164
180
|
|
165
181
|
var files_selected = function(files) {
|
166
182
|
if (files.length > 0) {
|
167
|
-
var file = files[0], url =
|
183
|
+
var file = files[0], url = this.createObjectURL(file);
|
168
184
|
this.selected_files = files;
|
169
185
|
this._edited_value = url;
|
170
|
-
window.URL.revokeObjectURL(url);
|
171
186
|
set_info(File.filename(file), file.fileSize);
|
172
187
|
}
|
173
188
|
}.bind(this);
|
@@ -160,7 +160,7 @@ Spontaneous.Field.Image = (function($, S) {
|
|
160
160
|
if (files.length > 0) {
|
161
161
|
this.select_files(files);
|
162
162
|
var file = files[0],
|
163
|
-
url =
|
163
|
+
url = this.createObjectURL(file)
|
164
164
|
, image = this.image;
|
165
165
|
this._edited_value = url;
|
166
166
|
image.__start_upload = true;
|
@@ -177,8 +177,6 @@ Spontaneous.Field.Image = (function($, S) {
|
|
177
177
|
}
|
178
178
|
}.bind(this));
|
179
179
|
image.attr('src', url);
|
180
|
-
// see http://www.htmlfivewow.com/slide25
|
181
|
-
window.URL.revokeObjectURL(url);
|
182
180
|
}
|
183
181
|
return false;
|
184
182
|
}.bind(this);
|
@@ -306,13 +304,12 @@ Spontaneous.Field.Image = (function($, S) {
|
|
306
304
|
|
307
305
|
var files_selected = function(files) {
|
308
306
|
if (files.length > 0) {
|
309
|
-
var file = files[0], url =
|
307
|
+
var file = files[0], url = this.createObjectURL(file);
|
310
308
|
img.attr('src', url).removeClass('empty');
|
311
309
|
this.select_files(files);
|
312
310
|
img.attr('src', url);
|
313
311
|
this._edited_value = url;
|
314
312
|
this.image.attr('src', url);
|
315
|
-
window.URL.revokeObjectURL(url);
|
316
313
|
set_info(File.filename(file), file.fileSize, null, null);
|
317
314
|
}
|
318
315
|
}.bind(this);
|
@@ -1,12 +1,21 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
3
|
Sequel.migration do
|
4
|
+
no_transaction
|
4
5
|
up do
|
5
|
-
[:content, :
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
[:content, :spontaneous_content_history, :spontaneous_content_archive].each do |table|
|
7
|
+
begin
|
8
|
+
alter_table table do
|
9
|
+
add_column :content_hash, :varchar, size: 32
|
10
|
+
add_column :published_content_hash, :varchar, size: 32
|
11
|
+
add_column :content_hash_changed, :boolean, default: true
|
12
|
+
end
|
13
|
+
rescue ::Sequel::DatabaseError => e
|
14
|
+
# because syncing ignores the content_archive table
|
15
|
+
# if we run this migration, then sync, then re-run it
|
16
|
+
# (in the case where the production db is behind the dev db)
|
17
|
+
# this one table will throw an error
|
18
|
+
raise unless table == :spontaneous_content_archive
|
10
19
|
end
|
11
20
|
end
|
12
21
|
alter_table :content do
|
@@ -15,32 +24,34 @@ Sequel.migration do
|
|
15
24
|
|
16
25
|
# testing environment
|
17
26
|
if defined?(Content)
|
27
|
+
transaction do
|
18
28
|
|
19
|
-
|
29
|
+
self.logger = nil
|
20
30
|
|
21
|
-
|
31
|
+
state = Spontaneous::State.first
|
22
32
|
|
23
|
-
|
33
|
+
published_revision = state.nil? ? nil : state[:published_revision]
|
24
34
|
|
25
|
-
|
35
|
+
content_hash = published_content_hash = nil
|
26
36
|
|
27
|
-
|
37
|
+
model = Spontaneous::Model(:content)
|
28
38
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
39
|
+
update_content_hashes = Proc.new do |content|
|
40
|
+
published_content_hash = nil
|
41
|
+
content_hash = content.calculate_content_hash!
|
42
|
+
if published_revision
|
43
|
+
model.mapper.scope(published_revision, false) do
|
44
|
+
published = model[content.id]
|
45
|
+
published_content_hash = published.calculate_content_hash! if published
|
46
|
+
end
|
36
47
|
end
|
48
|
+
p [content.id, content.class, content.path, content_hash, published_content_hash] #if published_content_hash != content_hash
|
49
|
+
model.dataset.unfiltered.where(id: content.id).update(content_hash: content_hash, published_content_hash: published_content_hash, content_hash_changed: (content_hash != published_content_hash))
|
37
50
|
end
|
38
|
-
p [content.id, content.class, content.path, content_hash, published_content_hash] #if published_content_hash != content_hash
|
39
|
-
model.dataset.unfiltered.where(id: content.id).update(content_hash: content_hash, published_content_hash: published_content_hash, content_hash_changed: (content_hash != published_content_hash))
|
40
|
-
end
|
41
51
|
|
42
|
-
|
43
|
-
|
52
|
+
Content::Piece.dataset.order(Sequel.desc(:depth)).each(&update_content_hashes)
|
53
|
+
Content::Page.dataset.order(Sequel.desc(:depth)).each(&update_content_hashes)
|
54
|
+
end
|
44
55
|
end
|
45
56
|
end
|
46
57
|
|
@@ -1,12 +1,23 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
3
|
Sequel.migration do
|
4
|
+
no_transaction
|
4
5
|
up do
|
5
6
|
[:content, :spontaneous_content_archive, :spontaneous_content_history].each do |table|
|
6
|
-
|
7
|
-
|
7
|
+
begin
|
8
|
+
alter_table table do
|
9
|
+
add_column :content_hash_changed_at, :timestamp
|
10
|
+
end
|
11
|
+
rescue ::Sequel::DatabaseError => e
|
12
|
+
# because syncing ignores the content_archive table
|
13
|
+
# if we run this migration, then sync, then re-run it
|
14
|
+
# (in the case where the production db is behind the dev db)
|
15
|
+
# this one table will throw an error
|
16
|
+
raise unless table == :spontaneous_content_archive
|
17
|
+
end
|
18
|
+
transaction do
|
19
|
+
self[table].update(content_hash_changed_at: :modified_at)
|
8
20
|
end
|
9
|
-
self[table].update(content_hash_changed_at: :modified_at)
|
10
21
|
end
|
11
22
|
end
|
12
23
|
|
@@ -5,12 +5,16 @@ module Spontaneous::Asset
|
|
5
5
|
module Environment
|
6
6
|
def self.new(context)
|
7
7
|
if context.publishing?
|
8
|
-
|
8
|
+
publishing(context.site, context.revision, context.development?)
|
9
9
|
else
|
10
|
-
|
10
|
+
preview(context.site)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
def self.publishing(site, revision, development)
|
15
|
+
Publish.new(site, revision, development)
|
16
|
+
end
|
17
|
+
|
14
18
|
def self.preview(site = Spontaneous::Site.instance)
|
15
19
|
Preview.new(site)
|
16
20
|
end
|
@@ -125,11 +129,19 @@ module Spontaneous::Asset
|
|
125
129
|
|
126
130
|
def to_url(asset, body = false)
|
127
131
|
return asset if asset.is_a?(String)
|
132
|
+
query = {}
|
133
|
+
query['body'] = 1 if body
|
134
|
+
query[asset.digest] = nil if dynamic_fingerprint?
|
128
135
|
path = asset.logical_path
|
129
|
-
path = "#{path}
|
136
|
+
path = "#{path}?#{Rack::Utils.build_query(query)}" unless query.empty?
|
130
137
|
"/" << asset_mount_point << "/" << path
|
131
138
|
end
|
132
139
|
|
140
|
+
# include the asset fingerprint as a query param for cache busting
|
141
|
+
def dynamic_fingerprint?
|
142
|
+
true
|
143
|
+
end
|
144
|
+
|
133
145
|
def asset_mount_point
|
134
146
|
"assets"
|
135
147
|
end
|
@@ -175,6 +187,11 @@ module Spontaneous::Asset
|
|
175
187
|
@development || false
|
176
188
|
end
|
177
189
|
|
190
|
+
# include the asset fingerprint as a query param for cache busting
|
191
|
+
def dynamic_fingerprint?
|
192
|
+
false
|
193
|
+
end
|
194
|
+
|
178
195
|
# A proxy to the sprockets manifest that compiles assets on the first run
|
179
196
|
# then re-uses them on the second
|
180
197
|
class Manifest
|
@@ -202,29 +219,10 @@ module Spontaneous::Asset
|
|
202
219
|
unless (args.all? { |key| assets.key?(key) })
|
203
220
|
compile!(*args)
|
204
221
|
end
|
205
|
-
copy_assets_to_revision(args)
|
206
222
|
end
|
207
223
|
|
208
224
|
def compile!(*args)
|
209
225
|
@manifest.compile(*args)
|
210
|
-
copy_assets_to_revision(args)
|
211
|
-
end
|
212
|
-
|
213
|
-
def copy_assets_to_revision(logical_paths)
|
214
|
-
assets = @manifest.assets
|
215
|
-
paths = logical_paths.map { |a| assets[a] }.compact
|
216
|
-
source, dest = shared_asset_dir, revision_asset_dir
|
217
|
-
paths.each do |asset|
|
218
|
-
copy_asset_to_revision(source, dest, asset)
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def copy_asset_to_revision(source, dest, asset)
|
223
|
-
to = dest + asset
|
224
|
-
return if to.exist?
|
225
|
-
from = source + asset
|
226
|
-
to.dirname.mkpath
|
227
|
-
FileUtils.cp(from, to)
|
228
226
|
end
|
229
227
|
|
230
228
|
def asset_compilation_dir
|
@@ -70,7 +70,14 @@ module Spontaneous::Model
|
|
70
70
|
# => [#<ContentClass...>, #<ContentClass...>]
|
71
71
|
#
|
72
72
|
def to_proc
|
73
|
-
Proc.new { |obj| self
|
73
|
+
Proc.new { |obj| self.===(obj) }
|
74
|
+
end
|
75
|
+
|
76
|
+
# Expands type testing to include peeking inside PagePiece instances
|
77
|
+
def ===(other)
|
78
|
+
return true if super
|
79
|
+
return (self == other.content_class) if other.respond_to?(:content_class)
|
80
|
+
false
|
74
81
|
end
|
75
82
|
end
|
76
83
|
|
@@ -148,6 +155,10 @@ module Spontaneous::Model
|
|
148
155
|
|
149
156
|
alias_method :is_page?, :page?
|
150
157
|
|
158
|
+
def content_class
|
159
|
+
self
|
160
|
+
end
|
161
|
+
|
151
162
|
# Do not overwrite this method directly.
|
152
163
|
# If you want a page to render the content of another configure
|
153
164
|
# the type using Content::render
|
@@ -30,11 +30,6 @@ module Spontaneous::Model::Page
|
|
30
30
|
|
31
31
|
private :__create_private_root=, :__create_private_root?
|
32
32
|
|
33
|
-
def after_initialize
|
34
|
-
super
|
35
|
-
set_generated_slug
|
36
|
-
end
|
37
|
-
|
38
33
|
def before_create
|
39
34
|
place_in_page_tree
|
40
35
|
set_slug_from_dynamic_value
|
@@ -46,11 +41,6 @@ module Spontaneous::Model::Page
|
|
46
41
|
fix_generated_slug_conflicts
|
47
42
|
end
|
48
43
|
|
49
|
-
def set_generated_slug
|
50
|
-
return unless slug.nil?
|
51
|
-
self.slug = generate_default_slug
|
52
|
-
end
|
53
|
-
|
54
44
|
def fix_generated_slug_conflicts
|
55
45
|
o = s = slug || generate_default_slug
|
56
46
|
n = 0
|
@@ -183,9 +173,13 @@ module Spontaneous::Model::Page
|
|
183
173
|
end
|
184
174
|
end
|
185
175
|
|
176
|
+
def initialized_slug
|
177
|
+
return slug unless slug.nil?
|
178
|
+
self.slug = generate_default_slug
|
179
|
+
end
|
186
180
|
|
187
181
|
def calculate_path
|
188
|
-
calculate_path_with_slug(
|
182
|
+
calculate_path_with_slug(initialized_slug)
|
189
183
|
end
|
190
184
|
|
191
185
|
def calculate_path_with_slug(slug)
|
@@ -32,6 +32,12 @@ module Spontaneous
|
|
32
32
|
target
|
33
33
|
end
|
34
34
|
|
35
|
+
# Used by Spontaneous::Model::Core::=== to look inside PagePiece objects
|
36
|
+
# and test against the class of the target, not of the proxy
|
37
|
+
def content_class
|
38
|
+
target.class
|
39
|
+
end
|
40
|
+
|
35
41
|
def id
|
36
42
|
target.id
|
37
43
|
end
|
@@ -132,6 +132,7 @@ module Spontaneous::Publishing
|
|
132
132
|
:create_revision_directory,
|
133
133
|
:render_revision,
|
134
134
|
:generate_search_indexes,
|
135
|
+
:copy_assets,
|
135
136
|
:copy_static_files,
|
136
137
|
:generate_rackup_file,
|
137
138
|
:activate_revision,
|
@@ -148,6 +149,7 @@ require 'spontaneous/publishing/steps/create_revision_directory'
|
|
148
149
|
require 'spontaneous/publishing/steps/render_revision'
|
149
150
|
require 'spontaneous/publishing/steps/generate_search_indexes'
|
150
151
|
require 'spontaneous/publishing/steps/copy_static_files'
|
152
|
+
require 'spontaneous/publishing/steps/copy_assets'
|
151
153
|
require 'spontaneous/publishing/steps/generate_rackup_file'
|
152
154
|
require 'spontaneous/publishing/steps/activate_revision'
|
153
155
|
require 'spontaneous/publishing/steps/write_revision_file'
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Spontaneous::Publishing::Steps
|
2
|
+
class CopyAssets < BaseStep
|
3
|
+
|
4
|
+
def count
|
5
|
+
assets.length
|
6
|
+
end
|
7
|
+
|
8
|
+
def call
|
9
|
+
@progress.stage("copying assets")
|
10
|
+
ensure_asset_dir
|
11
|
+
assets.each do |logical_path, asset|
|
12
|
+
copy_asset(asset)
|
13
|
+
@progress.step(1, "'#{logical_path}' => '#{asset}'")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def rollback
|
18
|
+
FileUtils.rm_r(revision_asset) if File.exists?(revision_asset)
|
19
|
+
end
|
20
|
+
|
21
|
+
def ensure_asset_dir
|
22
|
+
dir = revision_asset
|
23
|
+
end
|
24
|
+
|
25
|
+
def copy_asset(asset)
|
26
|
+
['', '.gz'].each do |suffix|
|
27
|
+
copy_asset_file(asset + suffix)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def copy_asset_file(asset)
|
32
|
+
source = File.join(manifest.asset_compilation_dir, asset)
|
33
|
+
if File.exist?(source)
|
34
|
+
dest = ensure_dir File.join(revision_asset, asset)
|
35
|
+
link_file(source, dest)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def link_file(source, dest)
|
40
|
+
src_dev = File::stat(source).dev
|
41
|
+
dst_dev = File::stat(File.dirname(dest)).dev
|
42
|
+
if (src_dev == dst_dev)
|
43
|
+
FileUtils.ln(source, dest, :force => true)
|
44
|
+
else
|
45
|
+
FileUtils.cp(source, dest)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def revision_asset
|
50
|
+
@asset_dest ||= Pathname.new(Spontaneous.revision_dir(revision) / 'assets').tap do |path|
|
51
|
+
FileUtils.mkdir_p(path) unless File.exists?(path)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def ensure_dir(path)
|
56
|
+
dir = File.dirname(path)
|
57
|
+
FileUtils.mkdir_p(dir) unless File.exist?(dir)
|
58
|
+
path
|
59
|
+
end
|
60
|
+
|
61
|
+
def assets
|
62
|
+
manifest.assets
|
63
|
+
end
|
64
|
+
|
65
|
+
def manifest
|
66
|
+
environment.manifest
|
67
|
+
end
|
68
|
+
|
69
|
+
def environment
|
70
|
+
@environment ||= Spontaneous::Asset::Environment.publishing(site, revision, development?)
|
71
|
+
end
|
72
|
+
|
73
|
+
def development?
|
74
|
+
Spontaneous.development?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/spontaneous/version.rb
CHANGED
Binary file
|
Binary file
|
@@ -1110,7 +1110,7 @@ describe "Back" do
|
|
1110
1110
|
it "render SASS templates" do
|
1111
1111
|
get "/assets/css/sass_template.css"
|
1112
1112
|
assert last_response.ok?, "Should return 200 but got #{last_response.status}"
|
1113
|
-
last_response.body.must_match /color: #
|
1113
|
+
last_response.body.must_match /color: #fef/
|
1114
1114
|
end
|
1115
1115
|
|
1116
1116
|
it "compile CoffeeScript" do
|
@@ -53,10 +53,10 @@ describe "AssetBundler" do
|
|
53
53
|
compiled_css_path = Dir["#{@site.root}/public/@spontaneous/assets/*.css"].first
|
54
54
|
css = File.read(compiled_css_path)
|
55
55
|
css.must_match /\.simple \{\s+color: #aaa/
|
56
|
-
css.must_match /\.basic \{\s+color: #
|
57
|
-
css.must_match /\.complex \{\s+color: #
|
56
|
+
css.must_match /\.basic \{\s+color: #abc/
|
57
|
+
css.must_match /\.complex \{\s+color: #def;\s*width: #{Date.today.day}px/
|
58
58
|
css.must_match /\.subdir\.simple \{\s+color: #000;/
|
59
|
-
css.must_match /\.subdir\.complex \{\s+color: #
|
59
|
+
css.must_match /\.subdir\.complex \{\s+color: #aaa;\s+height: #{Date.today.day}px/
|
60
60
|
end
|
61
61
|
|
62
62
|
it "produce compressed CSS by default" do
|
@@ -65,10 +65,10 @@ describe "AssetBundler" do
|
|
65
65
|
compiled_css_path = Dir["#{@site.root}/public/@spontaneous/assets/spontaneous*.css"].first
|
66
66
|
css = File.read(compiled_css_path)
|
67
67
|
css.must_match /\.simple\{color:#aaa\}/
|
68
|
-
css.must_match /\.basic\{color:#
|
69
|
-
css.must_match /\.complex\{color:#
|
68
|
+
css.must_match /\.basic\{color:#abc\}/
|
69
|
+
css.must_match /\.complex\{color:#def;width:#{Date.today.day}px\}/
|
70
70
|
css.must_match /\.subdir\.simple\{color:#000\}/
|
71
|
-
css.must_match /\.subdir\.complex\{color:#
|
71
|
+
css.must_match /\.subdir\.complex\{color:#aaa;height:#{Date.today.day}px\}/
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
data/test/unit/test_assets.rb
CHANGED
@@ -6,9 +6,7 @@ require 'ostruct'
|
|
6
6
|
describe "Assets" do
|
7
7
|
include RackTestMethods
|
8
8
|
|
9
|
-
|
10
|
-
Spontaneous::Rack::Back.application(site)
|
11
|
-
end
|
9
|
+
let(:app) {Spontaneous::Rack::Back.application(site)}
|
12
10
|
|
13
11
|
module LiveSimulation
|
14
12
|
# simulate a production + publishing environment
|
@@ -59,6 +57,13 @@ describe "Assets" do
|
|
59
57
|
end
|
60
58
|
end
|
61
59
|
|
60
|
+
def asset_digest(asset_relative_path)
|
61
|
+
digest = context.asset_environment.environment.digest
|
62
|
+
digest.update(File.read(File.join(fixture_root, asset_relative_path)))
|
63
|
+
digest.hexdigest
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:y_png_digest) { asset_digest('public2/i/y.png') }
|
62
67
|
|
63
68
|
start do
|
64
69
|
fixture_root = File.expand_path("../../fixtures/assets", __FILE__)
|
@@ -136,16 +141,32 @@ describe "Assets" do
|
|
136
141
|
describe "development" do
|
137
142
|
let(:context) { development_context }
|
138
143
|
|
144
|
+
let(:a_js_digest) { asset_digest('public1/js/a.js') }
|
145
|
+
let(:b_js_digest) { asset_digest('public2/js/b.js') }
|
146
|
+
let(:c_js_digest) { asset_digest('public2/js/c.js') }
|
147
|
+
let(:x_js_digest) { asset_digest('public1/x.js') }
|
148
|
+
# these are compiled so fairly complex to calculate their digests
|
149
|
+
# not impossible, but annoying
|
150
|
+
let(:n_js_digest) { '74f175e03a4bdc8c807aba4ae0314938' }
|
151
|
+
let(:m_js_digest) { 'dd35b142dc75b6ec15b2138e9e91c0c3' }
|
152
|
+
let(:all_js_digest) { 'd406fc3c21d90828a2f0a718c89e8d99' }
|
153
|
+
|
154
|
+
let(:a_css_digest) { '7b04d295476986c24d8c77245943e5b9' }
|
155
|
+
let(:b_css_digest) { '266643993e14da14f2473d45f003bd2c' }
|
156
|
+
let(:c_css_digest) { 'fc8ba0d0aae64081dc00b8444a198fb8' }
|
157
|
+
let(:x_css_digest) { '2560aec2891794825eba770bf84823fb' }
|
158
|
+
let(:all_css_digest) { 'cf61c624b91b9ea126804291ac55bd5d' }
|
159
|
+
|
139
160
|
it "includes all js dependencies" do
|
140
161
|
result = context.scripts('js/all', 'js/m', 'js/c', 'x')
|
141
162
|
result.must_equal [
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
163
|
+
%|<script type="text/javascript" src="/assets/js/a.js?body=1&#{a_js_digest}"></script>|,
|
164
|
+
%|<script type="text/javascript" src="/assets/js/b.js?body=1&#{b_js_digest}"></script>|,
|
165
|
+
%|<script type="text/javascript" src="/assets/js/n.js?body=1&#{n_js_digest}"></script>|,
|
166
|
+
%|<script type="text/javascript" src="/assets/js/all.js?body=1&#{all_js_digest}"></script>|,
|
167
|
+
%|<script type="text/javascript" src="/assets/js/m.js?body=1&#{m_js_digest}"></script>|,
|
168
|
+
%|<script type="text/javascript" src="/assets/js/c.js?body=1&#{c_js_digest}"></script>|,
|
169
|
+
%|<script type="text/javascript" src="/assets/x.js?body=1&#{x_js_digest}"></script>|
|
149
170
|
].join("\n")
|
150
171
|
end
|
151
172
|
|
@@ -158,11 +179,11 @@ describe "Assets" do
|
|
158
179
|
it "includes all css dependencies" do
|
159
180
|
result = context.stylesheets('css/all', 'css/c', 'x')
|
160
181
|
result.must_equal [
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
182
|
+
%|<link rel="stylesheet" href="/assets/css/b.css?body=1&#{b_css_digest}" />|,
|
183
|
+
%|<link rel="stylesheet" href="/assets/css/a.css?body=1&#{a_css_digest}" />|,
|
184
|
+
%|<link rel="stylesheet" href="/assets/css/all.css?body=1&#{all_css_digest}" />|,
|
185
|
+
%|<link rel="stylesheet" href="/assets/css/c.css?body=1&#{c_css_digest}" />|,
|
186
|
+
%|<link rel="stylesheet" href="/assets/x.css?body=1&#{x_css_digest}" />|
|
166
187
|
].join("\n")
|
167
188
|
end
|
168
189
|
|
@@ -183,14 +204,24 @@ describe "Assets" do
|
|
183
204
|
let(:app) { Spontaneous::Rack::Back.application(site) }
|
184
205
|
let(:context) { preview_context }
|
185
206
|
|
207
|
+
let(:c_js_digest) { 'f669550dd7e10e9646ad781f44756950' }
|
208
|
+
let(:x_js_digest) { '6b4c9176b2838a4949a18284543fc19c' }
|
209
|
+
let(:n_js_digest) { '74f175e03a4bdc8c807aba4ae0314938' }
|
210
|
+
let(:m_js_digest) { 'dd35b142dc75b6ec15b2138e9e91c0c3' }
|
211
|
+
let(:all_js_digest) { 'cd1f681752f5038421be0bc5ea0e855d' }
|
212
|
+
|
213
|
+
let(:c_css_digest) { 'fc8ba0d0aae64081dc00b8444a198fb8' }
|
214
|
+
let(:x_css_digest) { '2560aec2891794825eba770bf84823fb' }
|
215
|
+
let(:all_css_digest) { 'bb2c289a27b3d5d4467dde6d60722fd3' }
|
216
|
+
|
186
217
|
describe "javascript" do
|
187
|
-
it "include scripts as separate files" do
|
218
|
+
it "include scripts as separate files with finger prints" do
|
188
219
|
result = context.scripts('js/all', 'js/m.js', 'js/c.js', 'x')
|
189
220
|
result.must_equal [
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
221
|
+
%|<script type="text/javascript" src="/assets/js/all.js?#{all_js_digest}"></script>|,
|
222
|
+
%|<script type="text/javascript" src="/assets/js/m.js?#{m_js_digest}"></script>|,
|
223
|
+
%|<script type="text/javascript" src="/assets/js/c.js?#{c_js_digest}"></script>|,
|
224
|
+
%|<script type="text/javascript" src="/assets/x.js?#{x_js_digest}"></script>|
|
194
225
|
].join("\n")
|
195
226
|
end
|
196
227
|
|
@@ -199,15 +230,15 @@ describe "Assets" do
|
|
199
230
|
it "handles urls passed as an array" do
|
200
231
|
result = context.scripts(['js/all', 'js/m.js'])
|
201
232
|
result.must_equal [
|
202
|
-
|
203
|
-
|
233
|
+
%|<script type="text/javascript" src="/assets/js/all.js?#{all_js_digest}"></script>|,
|
234
|
+
%|<script type="text/javascript" src="/assets/js/m.js?#{m_js_digest}"></script>|
|
204
235
|
].join("\n")
|
205
236
|
end
|
206
237
|
|
207
238
|
it "should ignore missing files" do
|
208
239
|
result = context.scripts('js/all', 'js/missing')
|
209
240
|
result.must_equal [
|
210
|
-
|
241
|
+
%|<script type="text/javascript" src="/assets/js/all.js?#{all_js_digest}"></script>|,
|
211
242
|
'<script type="text/javascript" src="js/missing.js"></script>'
|
212
243
|
].join("\n")
|
213
244
|
end
|
@@ -244,7 +275,7 @@ describe "Assets" do
|
|
244
275
|
context = preview_context
|
245
276
|
result = context.scripts('js/all', '//use.typekit.com/abcde', 'http://cdn.google.com/jquery.js', 'https://cdn.google.com/jquery.js')
|
246
277
|
result.must_equal [
|
247
|
-
|
278
|
+
%|<script type="text/javascript" src="/assets/js/all.js?#{all_js_digest}"></script>|,
|
248
279
|
'<script type="text/javascript" src="//use.typekit.com/abcde"></script>',
|
249
280
|
'<script type="text/javascript" src="http://cdn.google.com/jquery.js"></script>',
|
250
281
|
'<script type="text/javascript" src="https://cdn.google.com/jquery.js"></script>'
|
@@ -256,18 +287,18 @@ describe "Assets" do
|
|
256
287
|
it "include css files as separate links" do
|
257
288
|
result = context.stylesheets('css/all', 'css/c', 'x')
|
258
289
|
result.must_equal [
|
259
|
-
|
260
|
-
|
261
|
-
|
290
|
+
%|<link rel="stylesheet" href="/assets/css/all.css?#{all_css_digest}" />|,
|
291
|
+
%|<link rel="stylesheet" href="/assets/css/c.css?#{c_css_digest}" />|,
|
292
|
+
%|<link rel="stylesheet" href="/assets/x.css?#{x_css_digest}" />|
|
262
293
|
].join("\n")
|
263
294
|
end
|
264
295
|
|
265
296
|
it "allows passing scripts as an array" do
|
266
297
|
result = context.stylesheets(['css/all', 'css/c', 'x'])
|
267
298
|
result.must_equal [
|
268
|
-
|
269
|
-
|
270
|
-
|
299
|
+
%|<link rel="stylesheet" href="/assets/css/all.css?#{all_css_digest}" />|,
|
300
|
+
%|<link rel="stylesheet" href="/assets/css/c.css?#{c_css_digest}" />|,
|
301
|
+
%|<link rel="stylesheet" href="/assets/x.css?#{x_css_digest}" />|
|
271
302
|
].join("\n")
|
272
303
|
end
|
273
304
|
|
@@ -327,11 +358,11 @@ describe "Assets" do
|
|
327
358
|
|
328
359
|
it "should allow for embedding asset images into templates" do
|
329
360
|
result = renderer.render_string("${ asset_path 'i/y.png' }", @page.output(:html))
|
330
|
-
result.must_equal "/assets/i/y.png"
|
361
|
+
result.must_equal "/assets/i/y.png?#{y_png_digest}"
|
331
362
|
end
|
332
363
|
it "should allow for embedding asset urls into templates" do
|
333
364
|
result = renderer.render_string("${ asset_url 'i/y.png' }", @page.output(:html))
|
334
|
-
result.must_equal "url(/assets/i/y.png)"
|
365
|
+
result.must_equal "url(/assets/i/y.png?#{y_png_digest})"
|
335
366
|
end
|
336
367
|
end
|
337
368
|
end
|
@@ -340,11 +371,17 @@ describe "Assets" do
|
|
340
371
|
let(:app) { Spontaneous::Rack::Front.application(site) }
|
341
372
|
let(:context) { live_context }
|
342
373
|
let(:revision) { site.revision(context.revision) }
|
374
|
+
let(:progress) { Spontaneous::Publishing::Progress::Silent.new }
|
375
|
+
|
376
|
+
def publish_assets(revision)
|
377
|
+
context.asset_environment.manifest.compile!
|
378
|
+
Spontaneous::Publishing::Steps::CopyAssets.new(site, revision, [], progress).call
|
379
|
+
end
|
343
380
|
|
344
381
|
before do
|
345
382
|
FileUtils.rm_f(Spontaneous.revision_dir) if File.exist?(Spontaneous.revision_dir)
|
346
383
|
system "ln -nfs #{revision.root} #{Spontaneous.revision_dir}"
|
347
|
-
|
384
|
+
publish_assets(context.revision)
|
348
385
|
end
|
349
386
|
|
350
387
|
after do
|
@@ -352,14 +389,14 @@ describe "Assets" do
|
|
352
389
|
end
|
353
390
|
|
354
391
|
describe "javascript" do
|
355
|
-
let(:all_sha) { "
|
356
|
-
let(:x_sha) { "
|
392
|
+
let(:all_sha) { "ed62549e8edc1f61a1e27136602f01d9" }
|
393
|
+
let(:x_sha) { "66e92be1e412458f6ff02f4c5dd9beb1" }
|
357
394
|
it "bundles & fingerprints local scripts" do
|
358
395
|
result = context.scripts('js/all', 'js/m.js', 'js/c.js', 'x')
|
359
396
|
result.must_equal [
|
360
397
|
%(<script type="text/javascript" src="/assets/js/all-#{all_sha}.js"></script>),
|
361
|
-
'<script type="text/javascript" src="/assets/js/m-
|
362
|
-
'<script type="text/javascript" src="/assets/js/c-
|
398
|
+
'<script type="text/javascript" src="/assets/js/m-a5be7324bc314d5cf470a59c3732ef10.js"></script>',
|
399
|
+
'<script type="text/javascript" src="/assets/js/c-c24bcbb4f9647b078cc919746aa7fc3a.js"></script>',
|
363
400
|
%(<script type="text/javascript" src="/assets/x-#{x_sha}.js"></script>)
|
364
401
|
].join("\n")
|
365
402
|
end
|
@@ -413,6 +450,7 @@ describe "Assets" do
|
|
413
450
|
context = live_context
|
414
451
|
def context.revision; 100 end
|
415
452
|
revision = site.revision(context.revision)
|
453
|
+
publish_assets(context.revision)
|
416
454
|
manifest = Spontaneous::JSON.parse File.read(site.path("assets/tmp") + "manifest.json")
|
417
455
|
compiled = manifest[:assets][:"js/all.js"]
|
418
456
|
::File.open(site.path("assets/tmp")+compiled, 'w') do |file|
|
@@ -426,14 +464,14 @@ describe "Assets" do
|
|
426
464
|
end
|
427
465
|
|
428
466
|
describe "css" do
|
429
|
-
let(:all_sha) { "
|
430
|
-
let(:x_sha) { "
|
467
|
+
let(:all_sha) { "2e17f25ddeba996223a6cd1e28e7a319" }
|
468
|
+
let(:x_sha) { "2560aec2891794825eba770bf84823fb" }
|
431
469
|
|
432
470
|
it "bundles & fingerprints local stylesheets" do
|
433
471
|
result = context.stylesheets('css/all', 'css/a.css', 'x')
|
434
472
|
result.must_equal [
|
435
473
|
%(<link rel="stylesheet" href="/assets/css/all-#{all_sha}.css" />),
|
436
|
-
'<link rel="stylesheet" href="/assets/css/a-
|
474
|
+
'<link rel="stylesheet" href="/assets/css/a-0164c6d5b696ec2f2c5e70cade040da8.css" />',
|
437
475
|
%(<link rel="stylesheet" href="/assets/x-#{x_sha}.css" />)
|
438
476
|
].join("\n")
|
439
477
|
end
|
@@ -457,7 +495,7 @@ describe "Assets" do
|
|
457
495
|
].join("\n")
|
458
496
|
end
|
459
497
|
|
460
|
-
it "makes bundled
|
498
|
+
it "makes bundled stylesheets available under /assets" do
|
461
499
|
path = context.stylesheet_urls('css/all').first
|
462
500
|
get path
|
463
501
|
asset_path = revision.path(path)
|
@@ -499,17 +537,15 @@ describe "Assets" do
|
|
499
537
|
end
|
500
538
|
end
|
501
539
|
|
502
|
-
let(:y_sha) { "e2b6a69468b467c7414ae0e12124a66e" }
|
503
|
-
|
504
540
|
describe "images" do
|
505
541
|
it "bundles images and links using fingerprinted asset url" do
|
506
542
|
path = context.stylesheet_urls('css/image1').first
|
507
543
|
get path
|
508
544
|
assert last_response.ok?, "Recieved #{last_response.status} not 200"
|
509
545
|
result = last_response.body
|
510
|
-
result.must_match %r{background:url\(/assets/i/y-#{
|
546
|
+
result.must_match %r{background:url\(/assets/i/y-#{y_png_digest}\.png\)}
|
511
547
|
|
512
|
-
asset_path = revision.path("/assets/i/y-#{
|
548
|
+
asset_path = revision.path("/assets/i/y-#{y_png_digest}.png")
|
513
549
|
assert asset_path.exist?
|
514
550
|
end
|
515
551
|
|
@@ -526,8 +562,8 @@ describe "Assets" do
|
|
526
562
|
get path
|
527
563
|
assert last_response.ok?, "Recieved #{last_response.status} not 200"
|
528
564
|
result = last_response.body
|
529
|
-
result.must_match %r{background:url\(/assets/i/y-#{
|
530
|
-
asset_path = revision.path("/assets/i/y-#{
|
565
|
+
result.must_match %r{background:url\(/assets/i/y-#{y_png_digest}\.png\?query=true#hash\)}
|
566
|
+
asset_path = revision.path("/assets/i/y-#{y_png_digest}.png")
|
531
567
|
assert asset_path.exist?
|
532
568
|
end
|
533
569
|
end
|
@@ -537,11 +573,11 @@ describe "Assets" do
|
|
537
573
|
|
538
574
|
it "should allow for embedding asset images into templates" do
|
539
575
|
result = renderer.render_string("${ asset_path 'i/y.png' }", @page.output(:html))
|
540
|
-
result.must_equal "/assets/i/y-#{
|
576
|
+
result.must_equal "/assets/i/y-#{y_png_digest}.png"
|
541
577
|
end
|
542
578
|
it "should allow for embedding asset urls into templates" do
|
543
579
|
result = renderer.render_string("${ asset_url 'i/y.png' }", @page.output(:html))
|
544
|
-
result.must_equal "url(/assets/i/y-#{
|
580
|
+
result.must_equal "url(/assets/i/y-#{y_png_digest}.png)"
|
545
581
|
end
|
546
582
|
end
|
547
583
|
end
|
data/test/unit/test_content.rb
CHANGED
@@ -344,5 +344,15 @@ describe "Content" do
|
|
344
344
|
it "provides a to_proc method that makes filtering by class easy" do
|
345
345
|
@instances.select(&C).map(&:class).must_equal [C, C]
|
346
346
|
end
|
347
|
+
|
348
|
+
it "can filter pagepieces that point to an object of the given type" do
|
349
|
+
pps = @instances.map { |i| Spontaneous::PagePiece.new(nil, i, nil)}
|
350
|
+
pps.select(&P).map { |i| i.to_page.class }.must_equal [P, P]
|
351
|
+
end
|
352
|
+
|
353
|
+
it "can filter content instances out a list POROs" do
|
354
|
+
pps = [Object.new, Object.new, @instances.first]
|
355
|
+
pps.select(&P).map { |i| i.to_page.class }.must_equal [P]
|
356
|
+
end
|
347
357
|
end
|
348
358
|
end
|
@@ -469,6 +469,80 @@ describe "Publishing Pipeline" do
|
|
469
469
|
end
|
470
470
|
end
|
471
471
|
|
472
|
+
describe "CopyAssets" do
|
473
|
+
let(:step) { Spontaneous::Publishing::Steps::CopyAssets }
|
474
|
+
let(:application_path) { Pathname.new(File.expand_path("../../fixtures/example_application", __FILE__)) }
|
475
|
+
let(:fixtures_path) { application_path + "assets" }
|
476
|
+
let(:revision_root) { @site.revision_dir(revision) }
|
477
|
+
let(:environment) { Spontaneous::Asset::Environment.publishing(@site, revision, false) }
|
478
|
+
let(:manifest) { environment.manifest }
|
479
|
+
let(:assets) { environment.manifest.assets }
|
480
|
+
|
481
|
+
def assert_assets(revision)
|
482
|
+
revision_root = @site.revision_dir(revision)
|
483
|
+
assets.length.must_equal 3
|
484
|
+
assets.each do |logical_path, asset|
|
485
|
+
assert File.exist?(File.join(revision_root, 'assets', asset)), "asset '#{asset}' does not exist"
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
before do
|
490
|
+
FileUtils.cp_r(fixtures_path, @site.root)
|
491
|
+
File.exist?(@site.root / 'assets/css/site.css.scss').must_equal true
|
492
|
+
manifest.compile!('css/site.css', 'i/xes.png')
|
493
|
+
end
|
494
|
+
|
495
|
+
it "has the right shortcut name" do
|
496
|
+
step.to_sym.must_equal :copy_assets
|
497
|
+
end
|
498
|
+
|
499
|
+
it "sets the progress stage to 'copying files'" do
|
500
|
+
progress = mock
|
501
|
+
progress.stubs(:step)
|
502
|
+
progress.expects(:stage).with("copying assets").once
|
503
|
+
run_step(progress)
|
504
|
+
end
|
505
|
+
|
506
|
+
it "steps the progress once" do
|
507
|
+
progress = mock
|
508
|
+
progress.stubs(:stage)
|
509
|
+
progress.expects(:step).with(1, instance_of(String)).times(3)
|
510
|
+
run_step(progress)
|
511
|
+
end
|
512
|
+
|
513
|
+
it "gives its step count as the number of facets" do
|
514
|
+
step.count(@site, revision, nil).must_equal 3
|
515
|
+
end
|
516
|
+
|
517
|
+
it "copies compiled assets to the revision's asset dir" do
|
518
|
+
run_step
|
519
|
+
assert_assets(revision)
|
520
|
+
end
|
521
|
+
|
522
|
+
it "copies compressed assets to the revision's asset dir" do
|
523
|
+
asset = assets.values.first
|
524
|
+
compressed = asset + '.gz'
|
525
|
+
FileUtils.cp(manifest.asset_compilation_dir + asset, manifest.asset_compilation_dir + compressed)
|
526
|
+
run_step
|
527
|
+
assert File.exist?(File.join(revision_root, 'assets', compressed)), "#{compressed} should exist"
|
528
|
+
end
|
529
|
+
|
530
|
+
it "deletes the copied files on rollback" do
|
531
|
+
instance = run_step
|
532
|
+
instance.rollback
|
533
|
+
refute File.exist?(File.join(revision_root, "assets"))
|
534
|
+
end
|
535
|
+
|
536
|
+
it "runs rollback after throwing an exception" do
|
537
|
+
instance = mock
|
538
|
+
step.expects(:new).returns(instance)
|
539
|
+
instance.expects(:call).raises(Exception)
|
540
|
+
instance.expects(:rollback)
|
541
|
+
lambda{ run_step }.must_raise(Exception)
|
542
|
+
end
|
543
|
+
|
544
|
+
end
|
545
|
+
|
472
546
|
describe "GenerateRackupFile" do
|
473
547
|
let(:step) { Spontaneous::Publishing::Steps::GenerateRackupFile }
|
474
548
|
let(:rackup_path) { @site.revision_dir(revision) / "config.ru" }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spontaneous
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.0.
|
4
|
+
version: 0.2.0.beta8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Garry Hill
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -887,6 +887,7 @@ files:
|
|
887
887
|
- lib/spontaneous/publishing/steps/activate_revision.rb
|
888
888
|
- lib/spontaneous/publishing/steps/archive_old_revisions.rb
|
889
889
|
- lib/spontaneous/publishing/steps/base_step.rb
|
890
|
+
- lib/spontaneous/publishing/steps/copy_assets.rb
|
890
891
|
- lib/spontaneous/publishing/steps/copy_static_files.rb
|
891
892
|
- lib/spontaneous/publishing/steps/create_revision_directory.rb
|
892
893
|
- lib/spontaneous/publishing/steps/generate_rackup_file.rb
|
@@ -1030,6 +1031,9 @@ files:
|
|
1030
1031
|
- test/fixtures/example_application/Gemfile
|
1031
1032
|
- test/fixtures/example_application/Gemfile.lock
|
1032
1033
|
- test/fixtures/example_application/Rakefile
|
1034
|
+
- test/fixtures/example_application/assets/css/site.css.scss
|
1035
|
+
- test/fixtures/example_application/assets/i/sine_waves.png
|
1036
|
+
- test/fixtures/example_application/assets/i/xes.png
|
1033
1037
|
- test/fixtures/example_application/config/back.rb
|
1034
1038
|
- test/fixtures/example_application/config/back.ru
|
1035
1039
|
- test/fixtures/example_application/config/back.yml
|
@@ -1369,6 +1373,9 @@ test_files:
|
|
1369
1373
|
- test/fixtures/example_application/Gemfile
|
1370
1374
|
- test/fixtures/example_application/Gemfile.lock
|
1371
1375
|
- test/fixtures/example_application/Rakefile
|
1376
|
+
- test/fixtures/example_application/assets/css/site.css.scss
|
1377
|
+
- test/fixtures/example_application/assets/i/sine_waves.png
|
1378
|
+
- test/fixtures/example_application/assets/i/xes.png
|
1372
1379
|
- test/fixtures/example_application/config/back.rb
|
1373
1380
|
- test/fixtures/example_application/config/back.ru
|
1374
1381
|
- test/fixtures/example_application/config/back.yml
|