spontaneous 0.2.0.beta9 → 0.2.0.beta10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +61 -0
- data/LICENSE +18 -17
- data/Rakefile +1 -1
- data/application/css/core.css.scss +1 -1
- data/application/css/dialogue.css.scss +8 -20
- data/application/js/preview.js +28 -7
- data/application/js/publish.js +15 -4
- data/application/js/top_bar.js +0 -16
- data/application/js/views/piece_view.js +1 -1
- data/lib/spontaneous/asset/environment.rb +16 -1
- data/lib/spontaneous/box.rb +68 -0
- data/lib/spontaneous/capistrano/deploy.rb +7 -4
- data/lib/spontaneous/capistrano/sync.rb +2 -2
- data/lib/spontaneous/cli/init.rb +70 -19
- data/lib/spontaneous/cli/init/db.rb +34 -55
- data/lib/spontaneous/cli/init/mysql.rb +5 -5
- data/lib/spontaneous/cli/init/postgresql.rb +8 -9
- data/lib/spontaneous/cli/init/sqlite.rb +1 -2
- data/lib/spontaneous/cli/migrate.rb +0 -1
- data/lib/spontaneous/cli/site.rb +4 -0
- data/lib/spontaneous/collections/entry_set.rb +11 -0
- data/lib/spontaneous/data_mapper/content_model.rb +2 -0
- data/lib/spontaneous/data_mapper/content_model/serialization.rb +2 -2
- data/lib/spontaneous/extensions/array.rb +12 -2
- data/lib/spontaneous/field/base.rb +10 -0
- data/lib/spontaneous/field/file.rb +32 -2
- data/lib/spontaneous/field/image.rb +24 -2
- data/lib/spontaneous/field/select.rb +8 -0
- data/lib/spontaneous/field/webvideo.rb +8 -0
- data/lib/spontaneous/generators/site/config/initializers/fields.rb +55 -0
- data/lib/spontaneous/json.rb +3 -2
- data/lib/spontaneous/logger.rb +2 -2
- data/lib/spontaneous/media/file.rb +3 -3
- data/lib/spontaneous/media/image/attributes.rb +72 -6
- data/lib/spontaneous/media/image/renderable.rb +53 -20
- data/lib/spontaneous/media/store.rb +3 -3
- data/lib/spontaneous/media/store/backend.rb +16 -0
- data/lib/spontaneous/media/store/cloud.rb +52 -12
- data/lib/spontaneous/media/store/local.rb +6 -3
- data/lib/spontaneous/model.rb +3 -0
- data/lib/spontaneous/model/core/entries.rb +34 -13
- data/lib/spontaneous/model/core/entry.rb +3 -1
- data/lib/spontaneous/model/page/controllers.rb +1 -2
- data/lib/spontaneous/model/page/paths.rb +18 -7
- data/lib/spontaneous/output/context.rb +0 -8
- data/lib/spontaneous/output/template/renderer.rb +2 -0
- data/lib/spontaneous/plugins/application/state.rb +0 -4
- data/lib/spontaneous/prototypes/field_prototype.rb +4 -0
- data/lib/spontaneous/publishing/immediate.rb +0 -5
- data/lib/spontaneous/publishing/progress.rb +2 -2
- data/lib/spontaneous/publishing/rerender.rb +1 -4
- data/lib/spontaneous/publishing/simultaneous.rb +19 -17
- data/lib/spontaneous/publishing/steps.rb +12 -3
- data/lib/spontaneous/rack.rb +2 -0
- data/lib/spontaneous/rack/asset_server.rb +5 -2
- data/lib/spontaneous/rack/back.rb +9 -1
- data/lib/spontaneous/rack/back/base.rb +1 -0
- data/lib/spontaneous/rack/back/changes.rb +5 -0
- data/lib/spontaneous/rack/back/preview.rb +4 -4
- data/lib/spontaneous/rack/back/private.rb +11 -0
- data/lib/spontaneous/rack/middleware/scope.rb +16 -4
- data/lib/spontaneous/rack/page_controller.rb +2 -2
- data/lib/spontaneous/rack/public.rb +52 -4
- data/lib/spontaneous/sequel.rb +10 -13
- data/lib/spontaneous/site.rb +28 -8
- data/lib/spontaneous/site/publishing.rb +1 -1
- data/lib/spontaneous/site/storage.rb +7 -4
- data/lib/spontaneous/tasks/environment.rake +3 -0
- data/lib/spontaneous/utils/database/postgres_dumper.rb +23 -2
- data/lib/spontaneous/version.rb +1 -1
- data/spontaneous.gemspec +7 -12
- data/test/fixtures/assets/public1/css/data.css.scss +1 -1
- data/test/functional/test_application.rb +15 -0
- data/test/functional/test_cli.rb +109 -3
- data/test/functional/test_front.rb +108 -10
- data/test/test_helper.rb +3 -3
- data/test/unit/fields/test_boolean_fields.rb +80 -0
- data/test/unit/fields/test_date_fields.rb +47 -0
- data/test/unit/fields/test_file_field.rb +210 -0
- data/test/unit/{test_images.rb → fields/test_image_fields.rb} +133 -15
- data/test/unit/fields/test_location_fields.rb +41 -0
- data/test/unit/fields/test_option_fields.rb +61 -0
- data/test/unit/fields/test_tag_list_fields.rb +45 -0
- data/test/unit/fields/test_text_fields.rb +124 -0
- data/test/unit/fields/test_web_video_fields.rb +198 -0
- data/test/unit/test_assets.rb +22 -22
- data/test/unit/test_boxes.rb +34 -13
- data/test/unit/test_changesets.rb +1 -0
- data/test/unit/test_extensions.rb +17 -0
- data/test/unit/test_fields.rb +20 -643
- data/test/unit/test_media.rb +9 -9
- data/test/unit/test_page.rb +47 -0
- data/test/unit/test_publishing_pipeline.rb +2 -2
- data/test/unit/test_serialisation.rb +37 -0
- data/test/unit/test_storage.rb +42 -3
- metadata +37 -17
@@ -53,6 +53,12 @@ module Spontaneous
|
|
53
53
|
def export(user)
|
54
54
|
{}
|
55
55
|
end
|
56
|
+
|
57
|
+
# Allows for field type classes to map a human readable default value
|
58
|
+
# to the correct serialized value
|
59
|
+
def make_default_value(instance, value)
|
60
|
+
value
|
61
|
+
end
|
56
62
|
end
|
57
63
|
|
58
64
|
extend ClassMethods
|
@@ -380,6 +386,10 @@ module Spontaneous
|
|
380
386
|
self.prototype.owner
|
381
387
|
end
|
382
388
|
|
389
|
+
def site
|
390
|
+
owner.try(:site)
|
391
|
+
end
|
392
|
+
|
383
393
|
def owner_sid
|
384
394
|
schema_owner.schema_id
|
385
395
|
end
|
@@ -7,6 +7,12 @@ module Spontaneous::Field
|
|
7
7
|
class File < Base
|
8
8
|
has_editor
|
9
9
|
|
10
|
+
def blank?
|
11
|
+
values[:path].blank?
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :empty?, :blank?
|
15
|
+
|
10
16
|
# In the case of clearing the field we will have been given a pending_value of ""
|
11
17
|
# we don't want that to run asynchronously
|
12
18
|
def asynchronous?
|
@@ -15,7 +21,7 @@ module Spontaneous::Field
|
|
15
21
|
end
|
16
22
|
|
17
23
|
def outputs
|
18
|
-
[:html, :path, :filesize, :filename]
|
24
|
+
[:html, :path, :filesize, :filename, :storage_name]
|
19
25
|
end
|
20
26
|
|
21
27
|
def set_pending_value(value, site)
|
@@ -115,6 +121,17 @@ module Spontaneous::Field
|
|
115
121
|
generate_path(input, site)
|
116
122
|
end
|
117
123
|
|
124
|
+
def generate_storage_name(input, site)
|
125
|
+
if (storage = input.try(:storage))
|
126
|
+
return storage.name
|
127
|
+
end
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
|
131
|
+
def storage
|
132
|
+
site.storage(storage_name)
|
133
|
+
end
|
134
|
+
|
118
135
|
def export(user = nil)
|
119
136
|
super(user).merge({
|
120
137
|
:processed_value => processed_values
|
@@ -133,8 +150,21 @@ module Spontaneous::Field
|
|
133
150
|
@file_info ||= Spontaneous::JSON.parse(unprocessed_value)
|
134
151
|
end
|
135
152
|
|
153
|
+
def value(format = :html)
|
154
|
+
case format
|
155
|
+
when :html, "html"
|
156
|
+
path
|
157
|
+
else
|
158
|
+
super
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
136
162
|
def path
|
137
|
-
|
163
|
+
storage.to_url(super)
|
164
|
+
end
|
165
|
+
|
166
|
+
def url
|
167
|
+
path
|
138
168
|
end
|
139
169
|
|
140
170
|
self.register
|
@@ -46,12 +46,26 @@ module Spontaneous::Field
|
|
46
46
|
[ {}, proc { width 300 } ]
|
47
47
|
end
|
48
48
|
|
49
|
+
def self.default_attributes
|
50
|
+
@default_attributes ||= {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.default_attributes=(default_attributes = {})
|
54
|
+
@default_attributes = default_attributes
|
55
|
+
end
|
56
|
+
|
49
57
|
def image?
|
50
58
|
true
|
51
59
|
end
|
52
60
|
|
61
|
+
def blank?
|
62
|
+
original.blank?
|
63
|
+
end
|
64
|
+
|
53
65
|
def sizes
|
54
|
-
@sizes ||= Hash.new { |hash, key|
|
66
|
+
@sizes ||= Hash.new { |hash, key|
|
67
|
+
hash[key] = S::Media::Image::Attributes.new(site, processed_values[key])
|
68
|
+
}
|
55
69
|
end
|
56
70
|
|
57
71
|
# value used to show conflicts between the current value and the value they're attempting to enter
|
@@ -93,6 +107,10 @@ module Spontaneous::Field
|
|
93
107
|
original.src
|
94
108
|
end
|
95
109
|
|
110
|
+
def url
|
111
|
+
original.url
|
112
|
+
end
|
113
|
+
|
96
114
|
def filepath
|
97
115
|
unprocessed_value
|
98
116
|
end
|
@@ -122,8 +140,12 @@ module Spontaneous::Field
|
|
122
140
|
|
123
141
|
|
124
142
|
def export(user = nil)
|
143
|
+
processed = Hash[outputs.map { |size|
|
144
|
+
[size, sizes[size].export(user)]
|
145
|
+
}]
|
146
|
+
processed.update(__pending__: pending_value) if has_pending_value?
|
125
147
|
super(user).merge({
|
126
|
-
:
|
148
|
+
processed_value: processed
|
127
149
|
})
|
128
150
|
end
|
129
151
|
|
@@ -78,6 +78,14 @@ module Spontaneous::Field
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
+
# Maps a configured default value to the appropriate JSON encoded [value, label] array
|
82
|
+
def self.make_default_value(instance, value)
|
83
|
+
return nil if value.blank?
|
84
|
+
option = option_list(instance.owner).detect { |opt, label| opt == value }
|
85
|
+
return nil if option.nil?
|
86
|
+
Spontaneous::JSON.encode option
|
87
|
+
end
|
88
|
+
|
81
89
|
def option_list
|
82
90
|
self.class.option_list(self.owner)
|
83
91
|
end
|
@@ -75,6 +75,10 @@ module Spontaneous::Field
|
|
75
75
|
hash[k] = 0 if v == false
|
76
76
|
}
|
77
77
|
end
|
78
|
+
|
79
|
+
def name
|
80
|
+
self.class.id
|
81
|
+
end
|
78
82
|
end
|
79
83
|
|
80
84
|
def self.providers
|
@@ -151,6 +155,10 @@ module Spontaneous::Field
|
|
151
155
|
src
|
152
156
|
end
|
153
157
|
|
158
|
+
def aspect_ratio
|
159
|
+
values.fetch(:width, 1).to_f / values.fetch(:height, 1).to_f
|
160
|
+
end
|
161
|
+
|
154
162
|
self.register(:webvideo)
|
155
163
|
end
|
156
164
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# The following controls the default render output or image fields.
|
2
|
+
#
|
3
|
+
# By default inserting an image field instance into a template like this:
|
4
|
+
#
|
5
|
+
# ${ image }
|
6
|
+
#
|
7
|
+
# will output an `img` tag with the image's `src` attribute and an empty `alt`
|
8
|
+
# value:
|
9
|
+
#
|
10
|
+
# <img src="/path/to/image.jpg" alt="" />
|
11
|
+
#
|
12
|
+
# You can override the default attributes by setting an options hash here:
|
13
|
+
#
|
14
|
+
Spontaneous::Field::Image.default_attributes = {
|
15
|
+
# Include the image's natural width & height by default when rendering an image field
|
16
|
+
# size: true,
|
17
|
+
|
18
|
+
# Include only the images’ natural width
|
19
|
+
# `true`, `:auto` or `'auto'` are equivalent
|
20
|
+
|
21
|
+
# width: true,
|
22
|
+
|
23
|
+
# Force all images to render at a fixed width (odd but possible)
|
24
|
+
|
25
|
+
# width: 42,
|
26
|
+
|
27
|
+
# Or the same for the image height:
|
28
|
+
|
29
|
+
# height: true,
|
30
|
+
# height: 42,
|
31
|
+
|
32
|
+
# Set a default alt attribute (not generally recommended)
|
33
|
+
|
34
|
+
# alt: 'Inappropriate',
|
35
|
+
|
36
|
+
# Or, more usefully, if you want to use a dynamic value based on the field
|
37
|
+
# being rendered then pass a proc
|
38
|
+
|
39
|
+
# alt: proc { |field| field.page.title },
|
40
|
+
|
41
|
+
# Or you can set any attribute you want by just adding it in here:
|
42
|
+
|
43
|
+
# crossorigin: 'crossorigin',
|
44
|
+
|
45
|
+
# If you want to set data attributes then you can pass a hash, e.g. to add a data-id attribute
|
46
|
+
# based on the images’ owning page e.g.
|
47
|
+
#
|
48
|
+
# <img src="..." alt="..." data-id="1234" />
|
49
|
+
#
|
50
|
+
# You would set a data attribute thusly:
|
51
|
+
|
52
|
+
# data: {
|
53
|
+
# id: proc { |field| field.owner.page.id }
|
54
|
+
# },
|
55
|
+
}
|
data/lib/spontaneous/json.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require 'yajl'
|
3
|
+
# require 'yajl'
|
4
|
+
require 'oj'
|
4
5
|
|
5
6
|
Oj.default_options = { mode: :compat } if defined?(Oj)
|
6
7
|
|
@@ -23,7 +24,7 @@ module Spontaneous
|
|
23
24
|
if defined?(::Yajl)
|
24
25
|
module YajlParser
|
25
26
|
def parser
|
26
|
-
Yajl::Parser.new(:
|
27
|
+
Yajl::Parser.new(symbolize_keys: true)
|
27
28
|
end
|
28
29
|
def encoder
|
29
30
|
Yajl::Encoder.new
|
data/lib/spontaneous/logger.rb
CHANGED
@@ -136,8 +136,8 @@ module Spontaneous
|
|
136
136
|
# Setup a new logger with options
|
137
137
|
#
|
138
138
|
def self.setup(options = {})
|
139
|
-
config_level = (SPOT_LOG_LEVEL || Spontaneous.env || :
|
140
|
-
config = Config[config_level]
|
139
|
+
config_level = (SPOT_LOG_LEVEL || Spontaneous.env || :production).to_sym # need this for SPOT_LOG_LEVEL
|
140
|
+
config = Config[config_level] || Config[:production] # default to a production level
|
141
141
|
stream = \
|
142
142
|
if logfile = options[:logfile]
|
143
143
|
FileUtils.mkdir_p(File.dirname(logfile)) unless File.directory?(File.dirname(logfile))
|
@@ -41,7 +41,7 @@ module Spontaneous::Media
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def url
|
44
|
-
storage.
|
44
|
+
storage.url_path(storage_path)
|
45
45
|
end
|
46
46
|
|
47
47
|
def mimetype
|
@@ -59,7 +59,7 @@ module Spontaneous::Media
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def storage
|
62
|
-
@storage ||= @site.
|
62
|
+
@storage ||= @site.storage_for_mimetype(mimetype)
|
63
63
|
end
|
64
64
|
|
65
65
|
def padded_id
|
@@ -95,7 +95,7 @@ module Spontaneous::Media
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def serialize
|
98
|
-
{ :
|
98
|
+
{ url: url, type: mimetype, filename: filename, storage_name: storage.name }
|
99
99
|
end
|
100
100
|
end
|
101
101
|
end
|
@@ -3,15 +3,19 @@ module Spontaneous::Media
|
|
3
3
|
class Attributes
|
4
4
|
include Renderable
|
5
5
|
|
6
|
-
attr_reader :
|
6
|
+
attr_reader :storage, :filepath, :storage
|
7
7
|
|
8
|
-
def initialize(params={})
|
9
|
-
params
|
10
|
-
@
|
8
|
+
def initialize(site, params={})
|
9
|
+
@params = params.try(:dup) || {}
|
10
|
+
@storage = site.storage(storage_name)
|
11
11
|
end
|
12
12
|
|
13
13
|
def serialize
|
14
|
-
{ :
|
14
|
+
{ src: src, width: width, height: height, dimensions: dimensions, filesize: filesize, storage_name: storage_name }
|
15
|
+
end
|
16
|
+
|
17
|
+
def export(user = nil)
|
18
|
+
serialize.delete_if { |k, v| v.nil? }
|
15
19
|
end
|
16
20
|
|
17
21
|
def inspect
|
@@ -19,7 +23,69 @@ module Spontaneous::Media
|
|
19
23
|
end
|
20
24
|
|
21
25
|
def blank?
|
22
|
-
src.blank?
|
26
|
+
@params[:src].blank?
|
27
|
+
end
|
28
|
+
|
29
|
+
alias_method :empty?, :blank?
|
30
|
+
|
31
|
+
def src
|
32
|
+
storage.to_url(@params[:src])
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method :url, :src
|
36
|
+
|
37
|
+
def storage_name
|
38
|
+
@params[:storage_name]
|
39
|
+
end
|
40
|
+
|
41
|
+
def width
|
42
|
+
@params[:width]
|
43
|
+
end
|
44
|
+
|
45
|
+
def height
|
46
|
+
@params[:height]
|
47
|
+
end
|
48
|
+
|
49
|
+
def filesize
|
50
|
+
@params[:filesize]
|
51
|
+
end
|
52
|
+
|
53
|
+
def dimensions
|
54
|
+
@params[:dimensions]
|
55
|
+
end
|
56
|
+
|
57
|
+
def filepath
|
58
|
+
@params[:path]
|
59
|
+
end
|
60
|
+
|
61
|
+
def src
|
62
|
+
storage.to_url(@params[:src])
|
63
|
+
end
|
64
|
+
|
65
|
+
alias_method :url, :src
|
66
|
+
|
67
|
+
def storage_name
|
68
|
+
@params[:storage_name]
|
69
|
+
end
|
70
|
+
|
71
|
+
def width
|
72
|
+
@params[:width]
|
73
|
+
end
|
74
|
+
|
75
|
+
def height
|
76
|
+
@params[:height]
|
77
|
+
end
|
78
|
+
|
79
|
+
def filesize
|
80
|
+
@params[:filesize]
|
81
|
+
end
|
82
|
+
|
83
|
+
def dimensions
|
84
|
+
@params[:dimensions]
|
85
|
+
end
|
86
|
+
|
87
|
+
def filepath
|
88
|
+
@params[:path]
|
23
89
|
end
|
24
90
|
|
25
91
|
# Will only work for files in local storage
|
@@ -14,32 +14,65 @@ module Spontaneous::Media::Image
|
|
14
14
|
|
15
15
|
alias_method :render_inline, :render
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
}
|
24
|
-
default_attr.delete(:width) if (width.nil? || width == 0)
|
25
|
-
default_attr.delete(:height) if (height.nil? || height == 0)
|
17
|
+
DEFAULT_SIZE_FLAGS = ['auto'.freeze, :auto, true].freeze
|
18
|
+
|
19
|
+
def to_html(opts={})
|
20
|
+
default_attr = { src: src, alt: "" }
|
21
|
+
attrs = Spontaneous::Field::Image.default_attributes.merge(opts)
|
22
|
+
|
26
23
|
if template_params && template_params.length > 0 && template_params[0].is_a?(Hash)
|
27
|
-
|
24
|
+
attrs = template_params[0].merge(attrs)
|
25
|
+
end
|
26
|
+
|
27
|
+
case attrs.delete(:size)
|
28
|
+
when true, :auto, 'auto'
|
29
|
+
attrs[:width] = width if has_width?
|
30
|
+
attrs[:height] = height if has_height?
|
28
31
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
|
33
|
+
if attrs.key?(:width) || attrs.key?(:height)
|
34
|
+
attrs.delete(:width) if (attrs.key?(:width) && !attrs[:width])
|
35
|
+
attrs.delete(:height) if (attrs.key?(:height) && !attrs[:height])
|
36
|
+
if has_width? && DEFAULT_SIZE_FLAGS.include?(attrs[:width])
|
37
|
+
attrs[:width] = width
|
38
|
+
end
|
39
|
+
if has_height? && DEFAULT_SIZE_FLAGS.include?(attrs[:height])
|
40
|
+
attrs[:height] = height
|
35
41
|
end
|
36
42
|
end
|
37
|
-
|
43
|
+
|
44
|
+
attrs = default_attr.merge(attrs)
|
45
|
+
params = parameterize_attributes(attrs)
|
46
|
+
%(<img #{params} />)
|
47
|
+
end
|
48
|
+
|
49
|
+
def parameterize_attributes(attrs, namespace = [])
|
38
50
|
params = []
|
39
|
-
|
40
|
-
|
51
|
+
attrs.each do |name, value|
|
52
|
+
key = (namespace + [name])
|
53
|
+
v = case value
|
54
|
+
when Hash
|
55
|
+
parameterize_attributes(value, key)
|
56
|
+
when Proc
|
57
|
+
%(#{key.join('-')}="#{value.call(self).to_s.escape_html}")
|
58
|
+
else
|
59
|
+
%(#{key.join('-')}="#{value.to_s.escape_html}")
|
60
|
+
end
|
61
|
+
params << v
|
41
62
|
end
|
42
|
-
|
63
|
+
params.join(' ')
|
64
|
+
end
|
65
|
+
|
66
|
+
def has_height?
|
67
|
+
has_dim?(height)
|
68
|
+
end
|
69
|
+
|
70
|
+
def has_width?
|
71
|
+
has_dim?(width)
|
72
|
+
end
|
73
|
+
|
74
|
+
def has_dim?(dim)
|
75
|
+
!(dim.nil? || dim == 0)
|
43
76
|
end
|
44
77
|
|
45
78
|
def to_s
|