spontaneous 0.2.0.alpha7 → 0.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -4
- data/Readme.markdown +1 -1
- data/application/css/definitions.css.scss +5 -0
- data/application/css/dialogue.css.scss +62 -0
- data/application/js/content.js +1 -1
- data/application/js/dom.js +1 -1
- data/application/js/event_source.js +3 -0
- data/application/js/{field_types/date_field.js → field/date.js} +2 -2
- data/application/js/{field_types/file_field.js → field/file.js} +2 -2
- data/application/js/{field_types/image_field.js → field/image.js} +54 -20
- data/application/js/{field_types/long_string_field.js → field/long_string.js} +2 -2
- data/application/js/{field_types/markdown_field.js → field/markdown.js} +2 -2
- data/application/js/{field_types/select_field.js → field/select.js} +2 -2
- data/application/js/{field_types/string_field.js → field/string.js} +21 -7
- data/application/js/{field_types/webvideo_field.js → field/webvideo.js} +2 -2
- data/application/js/field.js +2 -2
- data/application/js/publish.js +99 -19
- data/application/js/spontaneous.js +8 -8
- data/application/js/top_bar.js +6 -4
- data/db/migrations/20130109125023_add_page_publish_lock.rb +17 -0
- data/db/migrations/20130111161934_convert_bcrypt_passwords.rb +22 -0
- data/db/migrations/20130114120000_create_revision_tables.rb +106 -0
- data/db/migrations/20130116220423_add_index_to_archive.rb +9 -0
- data/lib/spontaneous/box.rb +53 -18
- data/lib/spontaneous/box_style.rb +2 -3
- data/lib/spontaneous/change.rb +39 -13
- data/lib/spontaneous/cli/fields.rb +29 -0
- data/lib/spontaneous/cli/init.rb +2 -2
- data/lib/spontaneous/cli/migrate.rb +0 -1
- data/lib/spontaneous/cli/server.rb +14 -10
- data/lib/spontaneous/cli/site.rb +20 -9
- data/lib/spontaneous/cli.rb +8 -6
- data/lib/spontaneous/collections/box_set.rb +11 -0
- data/lib/spontaneous/collections/field_set.rb +24 -1
- data/lib/spontaneous/concern.rb +37 -0
- data/lib/spontaneous/config.rb +3 -4
- data/lib/spontaneous/crypt/version.rb +130 -0
- data/lib/spontaneous/crypt.rb +84 -0
- data/lib/spontaneous/data_mapper/content_model/associations.rb +199 -0
- data/lib/spontaneous/data_mapper/content_model/column_accessors.rb +52 -0
- data/lib/spontaneous/data_mapper/content_model/instance_hooks.rb +34 -0
- data/lib/spontaneous/data_mapper/content_model/serialization.rb +54 -0
- data/lib/spontaneous/data_mapper/content_model/timestamps.rb +39 -0
- data/lib/spontaneous/data_mapper/content_model.rb +343 -0
- data/lib/spontaneous/data_mapper/content_table.rb +103 -0
- data/lib/spontaneous/data_mapper/dataset.rb +194 -0
- data/lib/spontaneous/data_mapper/scope.rb +195 -0
- data/lib/spontaneous/data_mapper.rb +161 -0
- data/lib/spontaneous/facet.rb +2 -2
- data/lib/spontaneous/field/base.rb +418 -0
- data/lib/spontaneous/field/date.rb +54 -0
- data/lib/spontaneous/{field_version.rb → field/field_version.rb} +1 -1
- data/lib/spontaneous/field/file.rb +100 -0
- data/lib/spontaneous/{field_types/image_field.rb → field/image.rb} +33 -33
- data/lib/spontaneous/{field_types/location_field.rb → field/location.rb} +2 -2
- data/lib/spontaneous/{field_types/long_string_field.rb → field/long_string.rb} +3 -3
- data/lib/spontaneous/field/markdown.rb +36 -0
- data/lib/spontaneous/{field_types/select_field.rb → field/select.rb} +4 -5
- data/lib/spontaneous/field/string.rb +17 -0
- data/lib/spontaneous/field/update.rb +156 -0
- data/lib/spontaneous/field/webvideo.rb +310 -0
- data/lib/spontaneous/field.rb +80 -0
- data/lib/spontaneous/generators/site/Gemfile.tt +2 -2
- data/lib/spontaneous/generators/site/config/environments/development.rb.tt +1 -1
- data/lib/spontaneous/generators/site/config/environments/production.rb.tt +1 -1
- data/lib/spontaneous/generators/site/lib/content.rb.tt +6 -0
- data/lib/spontaneous/generators/site/schema/box.rb.tt +3 -2
- data/lib/spontaneous/generators/site/schema/page.rb.tt +3 -1
- data/lib/spontaneous/generators/site/schema/piece.rb.tt +3 -1
- data/lib/spontaneous/generators/site/templates/layouts/standard.html.cut.tt +3 -1
- data/lib/spontaneous/generators/site.rb +4 -3
- data/lib/spontaneous/image_size.rb +8 -1
- data/lib/spontaneous/layout.rb +5 -1
- data/lib/spontaneous/loader.rb +2 -5
- data/lib/spontaneous/media/file.rb +11 -2
- data/lib/spontaneous/media/temp_file.rb +23 -0
- data/lib/spontaneous/media.rb +20 -39
- data/lib/spontaneous/{plugins → model/box}/allowed_types.rb +38 -17
- data/lib/spontaneous/model/box.rb +18 -0
- data/lib/spontaneous/{plugins → model/core}/aliases.rb +10 -14
- data/lib/spontaneous/{plugins → model/core}/boxes.rb +2 -2
- data/lib/spontaneous/{plugins → model/core}/content_groups.rb +2 -2
- data/lib/spontaneous/model/core/editor_class.rb +4 -0
- data/lib/spontaneous/{plugins → model/core}/entries.rb +19 -7
- data/lib/spontaneous/{plugins → model/core}/entry.rb +3 -3
- data/lib/spontaneous/{plugins → model/core}/fields.rb +38 -5
- data/lib/spontaneous/{plugins → model/core}/instance_code.rb +2 -2
- data/lib/spontaneous/{plugins → model/core}/media.rb +2 -12
- data/lib/spontaneous/{plugins → model/core}/modifications.rb +7 -6
- data/lib/spontaneous/model/core/page_search.rb +36 -0
- data/lib/spontaneous/{plugins → model/core}/permissions.rb +4 -4
- data/lib/spontaneous/{plugins → model/core}/prototypes.rb +4 -4
- data/lib/spontaneous/{plugins → model/core}/publishing.rb +93 -115
- data/lib/spontaneous/{plugins → model/core}/render.rb +2 -2
- data/lib/spontaneous/{plugins → model/core}/schema_hierarchy.rb +7 -11
- data/lib/spontaneous/model/core/schema_id.rb +65 -0
- data/lib/spontaneous/{plugins → model/core}/schema_title.rb +2 -2
- data/lib/spontaneous/{plugins → model/core}/serialisation.rb +2 -2
- data/lib/spontaneous/{plugins → model/core}/styles.rb +2 -2
- data/lib/spontaneous/{plugins → model/core}/supertype.rb +2 -2
- data/lib/spontaneous/{plugins → model/core}/visibility.rb +7 -48
- data/lib/spontaneous/model/core.rb +143 -0
- data/lib/spontaneous/{plugins → model/page}/controllers.rb +3 -3
- data/lib/spontaneous/{plugins → model}/page/formats.rb +2 -2
- data/lib/spontaneous/{plugins → model/page}/layouts.rb +2 -2
- data/lib/spontaneous/model/page/locks.rb +14 -0
- data/lib/spontaneous/{plugins → model/page}/page_tree.rb +3 -3
- data/lib/spontaneous/{plugins → model/page}/paths.rb +30 -12
- data/lib/spontaneous/{plugins → model}/page/request.rb +2 -2
- data/lib/spontaneous/{plugins → model/page}/site_map.rb +2 -2
- data/lib/spontaneous/model/page/site_timestamps.rb +44 -0
- data/lib/spontaneous/{page.rb → model/page.rb} +49 -28
- data/lib/spontaneous/{piece.rb → model/piece.rb} +7 -6
- data/lib/spontaneous/model.rb +97 -0
- data/lib/spontaneous/output/context.rb +1 -1
- data/lib/spontaneous/output/format.rb +4 -0
- data/lib/spontaneous/output/template/renderer.rb +2 -2
- data/lib/spontaneous/output.rb +2 -2
- data/lib/spontaneous/page_lock.rb +62 -0
- data/lib/spontaneous/page_piece.rb +1 -1
- data/lib/spontaneous/permissions/access_key.rb +9 -4
- data/lib/spontaneous/permissions/user.rb +19 -9
- data/lib/spontaneous/permissions.rb +2 -5
- data/lib/spontaneous/plugins/application/facets.rb +1 -2
- data/lib/spontaneous/plugins/application/features.rb +1 -1
- data/lib/spontaneous/plugins/application/paths.rb +1 -1
- data/lib/spontaneous/plugins/application/render.rb +1 -1
- data/lib/spontaneous/plugins/application/serialisation.rb +1 -1
- data/lib/spontaneous/plugins/application/state.rb +30 -1
- data/lib/spontaneous/plugins/application/system.rb +12 -12
- data/lib/spontaneous/prototypes/box_prototype.rb +1 -1
- data/lib/spontaneous/prototypes/field_prototype.rb +3 -6
- data/lib/spontaneous/prototypes/style_prototype.rb +1 -1
- data/lib/spontaneous/publishing/immediate.rb +77 -49
- data/lib/spontaneous/publishing/revision.rb +355 -0
- data/lib/spontaneous/publishing/simultaneous.rb +10 -49
- data/lib/spontaneous/publishing.rb +1 -0
- data/lib/spontaneous/rack/around_back.rb +1 -1
- data/lib/spontaneous/rack/around_front.rb +2 -4
- data/lib/spontaneous/rack/around_preview.rb +1 -1
- data/lib/spontaneous/rack/back.rb +80 -63
- data/lib/spontaneous/rack/cacheable_file.rb +2 -2
- data/lib/spontaneous/rack/cookie_authentication.rb +1 -1
- data/lib/spontaneous/rack/front.rb +1 -1
- data/lib/spontaneous/rack/helpers.rb +8 -9
- data/lib/spontaneous/{page_controller.rb → rack/page_controller.rb} +1 -1
- data/lib/spontaneous/rack/public.rb +3 -3
- data/lib/spontaneous/rack.rb +15 -15
- data/lib/spontaneous/schema/uid.rb +4 -1
- data/lib/spontaneous/schema.rb +57 -24
- data/lib/spontaneous/search/database.rb +12 -1
- data/lib/spontaneous/search/index.rb +34 -6
- data/lib/spontaneous/search/results.rb +1 -1
- data/lib/spontaneous/server.rb +3 -3
- data/lib/spontaneous/simultaneous.rb +53 -0
- data/lib/spontaneous/{plugins/site → site}/features.rb +2 -2
- data/lib/spontaneous/{plugins/site → site}/helpers.rb +2 -3
- data/lib/spontaneous/{plugins/site → site}/hooks.rb +2 -2
- data/lib/spontaneous/{plugins/site → site}/instance.rb +4 -6
- data/lib/spontaneous/{plugins/site → site}/level.rb +2 -2
- data/lib/spontaneous/{plugins/site → site}/map.rb +4 -4
- data/lib/spontaneous/{plugins/site → site}/paths.rb +2 -2
- data/lib/spontaneous/site/publishing.rb +89 -0
- data/lib/spontaneous/{plugins/site → site}/schema.rb +4 -4
- data/lib/spontaneous/{plugins/site → site}/search.rb +2 -2
- data/lib/spontaneous/{plugins/site → site}/selectors.rb +15 -7
- data/lib/spontaneous/{plugins/site → site}/state.rb +2 -2
- data/lib/spontaneous/{plugins/site → site}/storage.rb +2 -2
- data/lib/spontaneous/{plugins/site → site}/url.rb +2 -2
- data/lib/spontaneous/site.rb +31 -14
- data/lib/spontaneous/state.rb +5 -6
- data/lib/spontaneous/style.rb +3 -2
- data/lib/spontaneous/utils/database/mysql_dumper.rb +13 -0
- data/lib/spontaneous/utils/database/postgres_dumper.rb +5 -0
- data/lib/spontaneous/version.rb +1 -1
- data/lib/spontaneous.rb +34 -89
- data/spontaneous.gemspec +112 -114
- data/test/experimental/test_crypt.rb +158 -0
- data/test/experimental/test_features.rb +3 -3
- data/test/fixtures/example_application/config/environments/development.rb +1 -1
- data/test/fixtures/example_application/lib/content.rb +5 -0
- data/test/fixtures/example_application/schema/page.rb +2 -1
- data/test/fixtures/example_application/schema/piece.rb +3 -2
- data/test/fixtures/serialisation/class_hash.yaml.erb +5 -5
- data/test/fixtures/serialisation/root_hash.yaml.erb +8 -0
- data/test/functional/test_application.rb +12 -1
- data/test/functional/test_back.rb +80 -48
- data/test/functional/test_front.rb +39 -46
- data/test/functional/test_user_manager.rb +3 -9
- data/test/javascript/test_markdown.rb +2 -2
- data/test/test_helper.rb +78 -23
- data/test/unit/test_alias.rb +21 -15
- data/test/unit/test_asset_bundler.rb +3 -3
- data/test/unit/test_assets.rb +2 -2
- data/test/unit/test_async.rb +7 -6
- data/test/unit/test_authentication.rb +43 -37
- data/test/unit/test_boxes.rb +46 -21
- data/test/unit/test_changesets.rb +65 -20
- data/test/unit/test_config.rb +9 -9
- data/test/unit/test_content.rb +50 -51
- data/test/unit/test_content_inheritance.rb +6 -20
- data/test/unit/test_datamapper.rb +1330 -0
- data/test/unit/test_datamapper_content.rb +214 -0
- data/test/unit/test_fields.rb +543 -54
- data/test/unit/test_formats.rb +2 -3
- data/test/unit/test_generators.rb +6 -6
- data/test/unit/test_helpers.rb +1 -1
- data/test/unit/test_image_size.rb +10 -5
- data/test/unit/test_images.rb +17 -18
- data/test/unit/test_layouts.rb +18 -3
- data/test/unit/test_media.rb +74 -49
- data/test/unit/test_modifications.rb +43 -43
- data/test/unit/test_page.rb +7 -10
- data/test/unit/test_permissions.rb +3 -10
- data/test/unit/test_piece.rb +5 -6
- data/test/unit/test_plugins.rb +7 -14
- data/test/unit/test_prototypes.rb +3 -3
- data/test/unit/test_publishing.rb +49 -27
- data/test/unit/test_render.rb +46 -15
- data/test/unit/test_revisions.rb +124 -127
- data/test/unit/test_schema.rb +53 -58
- data/test/unit/test_search.rb +64 -16
- data/test/unit/test_serialisation.rb +4 -11
- data/test/unit/test_site.rb +11 -12
- data/test/unit/test_structure.rb +2 -5
- data/test/unit/test_styles.rb +22 -24
- data/test/unit/test_type_hierarchy.rb +7 -5
- data/test/unit/test_visibility.rb +79 -55
- metadata +128 -102
- data/lib/sequel/plugins/content_table_inheritance.rb +0 -203
- data/lib/sequel/plugins/scoped_table_name.rb +0 -54
- data/lib/spontaneous/content.rb +0 -129
- data/lib/spontaneous/field_types/date_field.rb +0 -56
- data/lib/spontaneous/field_types/field.rb +0 -302
- data/lib/spontaneous/field_types/file_field.rb +0 -68
- data/lib/spontaneous/field_types/markdown_field.rb +0 -38
- data/lib/spontaneous/field_types/string_field.rb +0 -19
- data/lib/spontaneous/field_types/webvideo_field.rb +0 -313
- data/lib/spontaneous/field_types.rb +0 -38
- data/lib/spontaneous/generators/site/lib/site.rb.tt +0 -4
- data/lib/spontaneous/plugins/field/editor_class.rb +0 -13
- data/lib/spontaneous/plugins/page/site_timestamps.rb +0 -28
- data/lib/spontaneous/plugins/page_search.rb +0 -63
- data/lib/spontaneous/plugins/schema_id.rb +0 -68
- data/lib/spontaneous/plugins/site/publishing.rb +0 -75
- data/lib/spontaneous/rack/fiber_pool.rb +0 -26
- data/test/unit/test_table_scoping.rb +0 -80
@@ -0,0 +1,310 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'open-uri'
|
4
|
+
require 'nokogiri'
|
5
|
+
|
6
|
+
module Spontaneous::Field
|
7
|
+
class WebVideo < Base
|
8
|
+
has_editor
|
9
|
+
|
10
|
+
def outputs
|
11
|
+
[:type, :id]
|
12
|
+
end
|
13
|
+
|
14
|
+
def id
|
15
|
+
value(:id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def video_type
|
19
|
+
value(:type)
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def generate_outputs(input)
|
24
|
+
values = {}
|
25
|
+
values[:html] = escape_html(input)
|
26
|
+
case input
|
27
|
+
when "", nil
|
28
|
+
# ignore this
|
29
|
+
when /youtube\.com.*\?.*v=([^&]+)/, /youtu.be\/([^&]+)/
|
30
|
+
id = $1
|
31
|
+
values.update(retrieve_youtube_metadata(id))
|
32
|
+
values[:id] = id
|
33
|
+
values[:type] = "youtube"
|
34
|
+
when /vimeo\.com\/(\d+)/
|
35
|
+
id = $1
|
36
|
+
values[:type] = "vimeo"
|
37
|
+
values.update(retrieve_vimeo_metadata(id))
|
38
|
+
values[:id] = id.to_s
|
39
|
+
else
|
40
|
+
logger.warn "WebVideo field doesn't recognise the URL '#{input}'"
|
41
|
+
end
|
42
|
+
values
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def render(format=:html, *args)
|
47
|
+
case format
|
48
|
+
when :html
|
49
|
+
to_html(*args)
|
50
|
+
when :json
|
51
|
+
to_json(*args)
|
52
|
+
else
|
53
|
+
value(format)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def to_html(*args)
|
59
|
+
opts = args.extract_options!
|
60
|
+
case video_type
|
61
|
+
when "youtube"
|
62
|
+
to_youtube_html(opts)
|
63
|
+
when "vimeo"
|
64
|
+
to_vimeo_html(opts)
|
65
|
+
else
|
66
|
+
value(:html)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def to_json(*args)
|
72
|
+
opts = args.extract_options!
|
73
|
+
params = \
|
74
|
+
case video_type
|
75
|
+
when "youtube"
|
76
|
+
youtube_attributes(opts)
|
77
|
+
when "vimeo"
|
78
|
+
vimeo_attributes(opts)
|
79
|
+
else
|
80
|
+
{:tagname => "iframe", :tag => "<iframe/>", :attr => {:src => value(:html)}}
|
81
|
+
end
|
82
|
+
Spontaneous.encode_json(params)
|
83
|
+
end
|
84
|
+
|
85
|
+
def src(opts = {})
|
86
|
+
case video_type
|
87
|
+
when "youtube"
|
88
|
+
youtube_src(opts)
|
89
|
+
when "vimeo"
|
90
|
+
vimeo_src(opts)
|
91
|
+
else
|
92
|
+
value(:html)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def ui_preview_value
|
97
|
+
# render(:html, :width => 480, :height => 270)
|
98
|
+
src
|
99
|
+
end
|
100
|
+
|
101
|
+
def retrieve_vimeo_metadata(id)
|
102
|
+
url = "http://vimeo.com/api/v2/video/%s.json" % id
|
103
|
+
response = \
|
104
|
+
begin
|
105
|
+
open(url).read
|
106
|
+
rescue => e
|
107
|
+
logger.error("Unable to retrieve metadata for video ##{id} from Vimeo: '#{e}'")
|
108
|
+
"[{}]"
|
109
|
+
end
|
110
|
+
metadata = Spontaneous.parse_json(response) rescue [{}]
|
111
|
+
metadata = metadata.first || {}
|
112
|
+
end
|
113
|
+
|
114
|
+
def retrieve_youtube_metadata(id)
|
115
|
+
url = "http://gdata.youtube.com/feeds/api/videos/%s?v=2" % id
|
116
|
+
begin
|
117
|
+
doc = Nokogiri::XML(open(url))
|
118
|
+
entry = doc.xpath("xmlns:entry")
|
119
|
+
|
120
|
+
{ "title" => entry.xpath("xmlns:title").text.strip,
|
121
|
+
"description" => entry.xpath("media:group/media:description").text.strip,
|
122
|
+
"thumbnail_large" => entry.xpath('media:group/media:thumbnail[@yt:name="hqdefault"]').first["url"].strip,
|
123
|
+
"thumbnail_small" => entry.xpath('media:group/media:thumbnail[@yt:name="default"]').first["url"].strip,
|
124
|
+
"user_name" => entry.xpath("xmlns:author/xmlns:name").text.strip,
|
125
|
+
"upload_date" => Time.parse(entry.xpath("xmlns:published").text.strip).strftime("%Y-%m-%d %H:%M:%S"),
|
126
|
+
"tags" => entry.xpath("media:group/media:keywords").text.strip,
|
127
|
+
"duration" => entry.xpath("media:group/yt:duration").first['seconds'].to_i,
|
128
|
+
"stats_number_of_likes" => entry.xpath("yt:rating").first['numLikes'].to_i,
|
129
|
+
"stats_number_of_plays" => entry.xpath("yt:statistics").first['viewCount'].to_i,
|
130
|
+
"stats_number_of_comments" => entry.xpath("gd:comments/gd:feedLink").first['countHint'].to_i }
|
131
|
+
rescue
|
132
|
+
{}
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def default_player_options
|
137
|
+
{
|
138
|
+
:width => 640,
|
139
|
+
:height => 360,
|
140
|
+
:fullscreen => true,
|
141
|
+
:api => false,
|
142
|
+
:autoplay => false,
|
143
|
+
:loop => false,
|
144
|
+
:showinfo => true
|
145
|
+
}.merge(prototype.options[:player] || {})
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
def to_vimeo_html(options = {})
|
150
|
+
params = vimeo_attributes(options)
|
151
|
+
|
152
|
+
attributes = make_html_attributes(params[:attr])
|
153
|
+
%(<iframe #{attributes}></iframe>)
|
154
|
+
end
|
155
|
+
|
156
|
+
def vimeo_attributes(options = {})
|
157
|
+
|
158
|
+
o = make_vimeo_options(options)
|
159
|
+
|
160
|
+
attributes = {
|
161
|
+
:type => "text/html",
|
162
|
+
:frameborder => "0",
|
163
|
+
:width => o.delete(:width),
|
164
|
+
:height => o.delete(:height)
|
165
|
+
}
|
166
|
+
attributes.update(:webkitAllowFullScreen => "yes", :allowFullScreen => "yes") if o[:fullscreen]
|
167
|
+
|
168
|
+
make_query_options!(o)
|
169
|
+
attributes[:src] = vimeo_src_with_options(o)
|
170
|
+
|
171
|
+
{:tagname => "iframe", :tag => "<iframe/>", :attr => attributes}
|
172
|
+
end
|
173
|
+
|
174
|
+
def make_vimeo_options(options = {})
|
175
|
+
o = default_player_options
|
176
|
+
vimeo_options = o.delete(:vimeo) || {}
|
177
|
+
|
178
|
+
o.merge!(vimeo_options)
|
179
|
+
|
180
|
+
if o.delete(:showinfo)
|
181
|
+
o[:portrait] = true
|
182
|
+
o[:title] = true
|
183
|
+
o[:byline] = true
|
184
|
+
else
|
185
|
+
o[:portrait] = false
|
186
|
+
o[:title] = false
|
187
|
+
o[:byline] = false
|
188
|
+
end
|
189
|
+
|
190
|
+
vimeo_options = options.delete(:vimeo) || {}
|
191
|
+
|
192
|
+
o = {
|
193
|
+
:portrait => true,
|
194
|
+
:title => true,
|
195
|
+
:byline => true,
|
196
|
+
:player_id => "vimeo#{owner.id}id#{value(:id)}"
|
197
|
+
}.merge(o).merge(vimeo_options).merge(options)
|
198
|
+
o
|
199
|
+
end
|
200
|
+
|
201
|
+
def vimeo_src(options = {})
|
202
|
+
o = make_vimeo_options(options)
|
203
|
+
make_query_options!(o)
|
204
|
+
vimeo_src_with_options(o)
|
205
|
+
end
|
206
|
+
|
207
|
+
def vimeo_src_with_options(o)
|
208
|
+
params = {
|
209
|
+
"title" => o[:title],
|
210
|
+
"byline" => o[:byline],
|
211
|
+
"portrait" => o[:portrait],
|
212
|
+
"autoplay" => o[:autoplay],
|
213
|
+
"loop" => o[:loop],
|
214
|
+
"api" => o[:api],
|
215
|
+
"player_id" => o[:player_id] }
|
216
|
+
params.update("color" => o[:color]) if o.key?(:color)
|
217
|
+
params = ::Rack::Utils.build_query(params)
|
218
|
+
"http://player.vimeo.com/video/#{value(:id)}?#{params}"
|
219
|
+
end
|
220
|
+
|
221
|
+
def to_youtube_html(options = {})
|
222
|
+
params = youtube_attributes(options)
|
223
|
+
attributes = make_html_attributes(params[:attr])
|
224
|
+
%(<iframe #{attributes}></iframe>)
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
def youtube_attributes(options = {})
|
229
|
+
o = make_youtube_options(options)
|
230
|
+
|
231
|
+
attributes = {
|
232
|
+
:type => "text/html",
|
233
|
+
:frameborder => "0",
|
234
|
+
:width => o.delete(:width),
|
235
|
+
:height => o.delete(:height)
|
236
|
+
}
|
237
|
+
|
238
|
+
make_query_options!(o)
|
239
|
+
|
240
|
+
attributes[:src] = youtube_src_with_options(o)
|
241
|
+
|
242
|
+
attributes.update(:webkitAllowFullScreen => "yes", :allowFullScreen => "yes") if o[:fullscreen]
|
243
|
+
|
244
|
+
{:tagname => "iframe", :tag => "<iframe/>", :attr => attributes}
|
245
|
+
end
|
246
|
+
|
247
|
+
def make_youtube_options(options = {})
|
248
|
+
o = default_player_options
|
249
|
+
youtube_options = o.delete(:youtube) || {}
|
250
|
+
|
251
|
+
o.merge!(youtube_options)
|
252
|
+
|
253
|
+
if o.delete(:showinfo)
|
254
|
+
o[:showinfo] = true
|
255
|
+
o[:showsearch] = true
|
256
|
+
else
|
257
|
+
o[:showinfo] = false
|
258
|
+
o[:showsearch] = false
|
259
|
+
end
|
260
|
+
|
261
|
+
youtube_options = options.delete(:youtube) || {}
|
262
|
+
o = {
|
263
|
+
:theme => "dark",
|
264
|
+
:hd => true,
|
265
|
+
:controls => true,
|
266
|
+
:showinfo => true,
|
267
|
+
:showsearch => true,
|
268
|
+
:autohide => 2,
|
269
|
+
:rel => true
|
270
|
+
}.merge(o).merge(youtube_options).merge(options)
|
271
|
+
end
|
272
|
+
|
273
|
+
def youtube_src(options = {})
|
274
|
+
o = make_youtube_options(options)
|
275
|
+
make_query_options!(o)
|
276
|
+
youtube_src_with_options(o)
|
277
|
+
end
|
278
|
+
|
279
|
+
def youtube_src_with_options(o)
|
280
|
+
params = ::Rack::Utils.build_query({
|
281
|
+
"modestbranding" => 1,
|
282
|
+
"theme" => o[:theme],
|
283
|
+
"hd" => o[:hd],
|
284
|
+
"fs" => o[:fullscreen],
|
285
|
+
"controls" => o[:controls],
|
286
|
+
"autoplay" => o[:autoplay],
|
287
|
+
"showinfo" => o[:showinfo],
|
288
|
+
"showsearch" => o[:showsearch],
|
289
|
+
"loop" => o[:loop],
|
290
|
+
"autohide" => o[:autohide],
|
291
|
+
"rel" => o[:rel],
|
292
|
+
"enablejsapi" => o[:api] })
|
293
|
+
"http://www.youtube.com/embed/#{value(:id)}?#{params}"
|
294
|
+
end
|
295
|
+
|
296
|
+
def make_html_attributes(attributes)
|
297
|
+
attributes.to_a.map { |name, value| "#{name}=\"#{escape_html(value)}\"" }.join(" ")
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
def make_query_options!(hash)
|
302
|
+
hash.each { |k, v|
|
303
|
+
hash[k] = 1 if v == true
|
304
|
+
hash[k] = 0 if v == false
|
305
|
+
}
|
306
|
+
end
|
307
|
+
|
308
|
+
self.register(:webvideo)
|
309
|
+
end
|
310
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Spontaneous
|
4
|
+
module Field
|
5
|
+
autoload :Base, "spontaneous/field/base"
|
6
|
+
autoload :FieldVersion, "spontaneous/field/field_version"
|
7
|
+
autoload :Update, "spontaneous/field/update"
|
8
|
+
|
9
|
+
@@type_map = {}
|
10
|
+
|
11
|
+
def self.register(klass, *labels)
|
12
|
+
labels.each do |label|
|
13
|
+
@@type_map[label.to_sym] = klass
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.[](label)
|
18
|
+
@@type_map[label.to_sym] || String
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.serialize_field(field)
|
22
|
+
[field.schema_id.to_s, field.version, field.unprocessed_value, field.processed_values]
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.deserialize_field(serialized_field)
|
26
|
+
{
|
27
|
+
:id => serialized_field[0],
|
28
|
+
:version => serialized_field[1],
|
29
|
+
:unprocessed_value => serialized_field[2],
|
30
|
+
:processed_values => serialized_field[3]
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Used to test for the validity of asynchronous updates.
|
35
|
+
#
|
36
|
+
# A to-the-second resolution would actually probably be fine as
|
37
|
+
# real updates will come from the user in meat-space time but
|
38
|
+
# why not use the full resolution available...
|
39
|
+
def self.timestamp(time = Time.now)
|
40
|
+
(time.to_f * 10000000).to_i
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.update(content, params, user, asynchronous = false)
|
44
|
+
fields = Hash[params.map { |sid, value| [content.fields.sid(sid), value] }]
|
45
|
+
Update.perform(fields, user, asynchronous)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.update_asynchronously(content, params, user)
|
49
|
+
update(content, params, user, true)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.set(field, value, user, asynchronous = false)
|
53
|
+
Update.perform({field => value}, user, asynchronous)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.set_asynchronously(field, value, user)
|
57
|
+
set(field, value, user, true)
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.find(*ids)
|
61
|
+
fields = ids.map { |id| resolve_id(id) }.compact
|
62
|
+
return fields.first if ids.length == 1
|
63
|
+
fields
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.resolve_id(id)
|
67
|
+
content_id, box_sid, field_sid = id.split("/")
|
68
|
+
field_sid, box_sid = box_sid, field_sid if field_sid.nil?
|
69
|
+
content = target = Spontaneous::Content.get(content_id)
|
70
|
+
return nil if target.nil?
|
71
|
+
target = content.boxes.sid(box_sid) if box_sid
|
72
|
+
return nil if target.nil?
|
73
|
+
target.fields.sid(field_sid)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
[:string, :long_string, :file, :image, :date, :markdown, :location, :webvideo, :select].each do |type|
|
79
|
+
require "spontaneous/field/#{type}"
|
80
|
+
end
|
@@ -13,8 +13,8 @@ gem 'capistrano', '~> 2.9'
|
|
13
13
|
# If you want to enable the built in search functionality then you must un-comment
|
14
14
|
# the xapian-full & xapian-fu dependencies below. They are not included by default
|
15
15
|
# because the xapian library takes a very long time to build.
|
16
|
-
#gem 'xapian-
|
17
|
-
#gem 'xapian-fu',
|
16
|
+
#gem 'xapian-ruby', "~> 1.2.12"
|
17
|
+
#gem 'xapian-fu', "~> 1.3"
|
18
18
|
|
19
19
|
# group :production do
|
20
20
|
# gem 'thin', '~> 1.3.1'
|
@@ -42,20 +42,21 @@ module Spontaneous
|
|
42
42
|
self.destination_root = self.destination_root / @site_name
|
43
43
|
directory "config"
|
44
44
|
directory "schema"
|
45
|
+
directory "lib"
|
45
46
|
directory "templates"
|
46
47
|
directory "public"
|
47
48
|
template "Gemfile.tt", "Gemfile"
|
48
49
|
template "Capfile.tt", "Capfile"
|
49
50
|
template "Rakefile.tt", "Rakefile"
|
50
|
-
template "lib/site.rb.tt", "lib/site.rb"
|
51
|
-
empty_directory "lib/tasks"
|
51
|
+
# template "lib/site.rb.tt", "lib/site.rb"
|
52
|
+
# empty_directory "lib/tasks"
|
52
53
|
empty_directory "log"
|
53
54
|
empty_directory "tmp"
|
54
55
|
empty_directory "cache/media"
|
55
56
|
empty_directory "cache/tmp"
|
56
57
|
empty_directory "cache/revisions"
|
57
58
|
copy_file ".gitignore"
|
58
|
-
template "lib/tasks/site.rake.tt", "lib/tasks/#{@site_name}.rake"
|
59
|
+
# template "lib/tasks/site.rake.tt", "lib/tasks/#{@site_name}.rake"
|
59
60
|
else
|
60
61
|
@valid = false
|
61
62
|
say "Invalid database selection '#{options.database}'. Valid options are: #{self.class.available_dbs.keys.join(', ')}", :red
|
@@ -15,7 +15,6 @@ module Spontaneous
|
|
15
15
|
else
|
16
16
|
File.open(file, 'rb') { |io| read_size(io) }
|
17
17
|
end
|
18
|
-
|
19
18
|
end
|
20
19
|
|
21
20
|
def read_size(file)
|
@@ -24,6 +23,7 @@ module Spontaneous
|
|
24
23
|
end
|
25
24
|
|
26
25
|
def image_type(file)
|
26
|
+
return Formats::EMPTY if file.size == 0
|
27
27
|
img_top = file.read(16)
|
28
28
|
bytes = img_top.unpack("C*")
|
29
29
|
file.seek(0,0)
|
@@ -64,6 +64,13 @@ module Spontaneous
|
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
67
|
+
class EMPTY
|
68
|
+
def initialize(file)
|
69
|
+
end
|
70
|
+
def size
|
71
|
+
[0, 0]
|
72
|
+
end
|
73
|
+
end
|
67
74
|
class GIF < Abstract
|
68
75
|
def read_size
|
69
76
|
@file.read_o(6)
|
data/lib/spontaneous/layout.rb
CHANGED
@@ -7,8 +7,12 @@ module Spontaneous
|
|
7
7
|
end
|
8
8
|
|
9
9
|
class Default < Layout
|
10
|
+
# If no named layouts have been defined first look for a layout
|
11
|
+
# matching the class of our owner, then default to the 'standard'
|
12
|
+
# layout.
|
10
13
|
def try_paths
|
11
|
-
|
14
|
+
named_layout = self.class.to_directory_name(owner)
|
15
|
+
[["layouts", named_layout], ["layouts", "standard"]]
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
data/lib/spontaneous/loader.rb
CHANGED
@@ -98,7 +98,7 @@ module Spontaneous
|
|
98
98
|
def is_site_page?(backtrace)
|
99
99
|
path, line, context = backtrace.split(":")
|
100
100
|
path = File.expand_path(path)
|
101
|
-
root = Site.instance.root
|
101
|
+
root = Spontaneous::Site.instance.root
|
102
102
|
path.start_with?(root)
|
103
103
|
end
|
104
104
|
|
@@ -242,9 +242,6 @@ module Spontaneous
|
|
242
242
|
# Removes the specified class and constant.
|
243
243
|
#
|
244
244
|
def remove_constant(const)
|
245
|
-
# return if Padrino::Reloader.exclude_constants.any? { |base| (const.to_s =~ /^#{base}/ || const.superclass.to_s =~ /^#{base}/) } &&
|
246
|
-
# !Padrino::Reloader.include_constants.any? { |base| (const.to_s =~ /^#{base}/ || const.superclass.to_s =~ /^#{base}/) }
|
247
|
-
|
248
245
|
Spontaneous.schema.delete(const)
|
249
246
|
|
250
247
|
parts = const.to_s.split("::")
|
@@ -378,7 +375,7 @@ module Spontaneous
|
|
378
375
|
end
|
379
376
|
|
380
377
|
def is_schema_class?(klass)
|
381
|
-
(klass < Spontaneous::
|
378
|
+
(klass < Spontaneous::Content or klass < Content::Box)
|
382
379
|
end
|
383
380
|
|
384
381
|
def remove_constant(const)
|
@@ -23,6 +23,7 @@ module Spontaneous::Media
|
|
23
23
|
def copy(existing_file)
|
24
24
|
@source = existing_file.respond_to?(:path) ? existing_file.path : existing_file
|
25
25
|
storage.copy(existing_file, storage_path, mimetype)
|
26
|
+
self
|
26
27
|
end
|
27
28
|
|
28
29
|
def url
|
@@ -46,11 +47,15 @@ module Spontaneous::Media
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def padded_id
|
49
|
-
owner.media_id
|
50
|
+
Spontaneous::Media.pad_id(owner.media_id)
|
50
51
|
end
|
51
52
|
|
52
53
|
def padded_revision
|
53
|
-
Spontaneous::
|
54
|
+
Spontaneous::Media.pad_revision(revision)
|
55
|
+
end
|
56
|
+
|
57
|
+
def revision
|
58
|
+
Spontaneous::Site.working_revision
|
54
59
|
end
|
55
60
|
|
56
61
|
def media_dir
|
@@ -74,5 +79,9 @@ module Spontaneous::Media
|
|
74
79
|
end
|
75
80
|
|
76
81
|
alias_method :filepath, :path
|
82
|
+
|
83
|
+
def serialize
|
84
|
+
{ :url => url, :mimetype => mimetype, :path => path, :filename => filename }
|
85
|
+
end
|
77
86
|
end
|
78
87
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Spontaneous::Media
|
6
|
+
# Represents a temporary file used to provide a media file that is visible
|
7
|
+
# publically under a /media/tmp/* URL for passing to file fields for
|
8
|
+
# asynchronous processing
|
9
|
+
class TempFile < File
|
10
|
+
|
11
|
+
def storage
|
12
|
+
Spontaneous::Site.default_storage
|
13
|
+
end
|
14
|
+
|
15
|
+
def media_dir
|
16
|
+
F.join("tmp", padded_id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def storage_path
|
20
|
+
["tmp", padded_id, filename]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|