spontaneous 0.2.0.beta7 → 0.2.0.beta8
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.
- 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
|