prismic.io 1.0.0.preview.1
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 +7 -0
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +37 -0
- data/README.md +43 -0
- data/Rakefile +1 -0
- data/lib/prismic.rb +167 -0
- data/lib/prismic/api.rb +94 -0
- data/lib/prismic/form.rb +19 -0
- data/lib/prismic/fragments.rb +11 -0
- data/lib/prismic/fragments/block.rb +4 -0
- data/lib/prismic/fragments/color.rb +31 -0
- data/lib/prismic/fragments/date.rb +15 -0
- data/lib/prismic/fragments/embed.rb +23 -0
- data/lib/prismic/fragments/image.rb +47 -0
- data/lib/prismic/fragments/link.rb +47 -0
- data/lib/prismic/fragments/multiple.rb +29 -0
- data/lib/prismic/fragments/number.rb +19 -0
- data/lib/prismic/fragments/select.rb +15 -0
- data/lib/prismic/fragments/structured_text.rb +200 -0
- data/lib/prismic/fragments/text.rb +15 -0
- data/lib/prismic/json_parsers.rb +174 -0
- data/lib/prismic/version.rb +5 -0
- data/prismic.gemspec +26 -0
- data/spec/fragments_spec.rb +372 -0
- data/spec/json_parsers_spec.rb +287 -0
- data/spec/prismic_spec.rb +237 -0
- data/spec/responses_mocks/api.json +192 -0
- data/spec/responses_mocks/document.json +170 -0
- data/spec/responses_mocks/fragments.json +176 -0
- data/spec/responses_mocks/structured_text_heading.json +12 -0
- data/spec/responses_mocks/structured_text_paragraph.json +30 -0
- data/spec/spec_helper.rb +10 -0
- metadata +157 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
module Prismic
|
2
|
+
module Fragments
|
3
|
+
class Embed
|
4
|
+
attr_accessor :embed_type, :provider, :url, :html, :o_embed_json
|
5
|
+
|
6
|
+
def initialize(embed_type, provider, url, html, o_embed_json)
|
7
|
+
@embed_type = embed_type
|
8
|
+
@provider = provider
|
9
|
+
@url = url
|
10
|
+
@html = html
|
11
|
+
@o_embed_json = o_embed_json
|
12
|
+
end
|
13
|
+
|
14
|
+
def as_html(link_resolver=nil)
|
15
|
+
<<-HTML
|
16
|
+
<div data-oembed="#@url"
|
17
|
+
data-oembed-type="#{@embed_type.downcase}"
|
18
|
+
data-oembed-provider="#{@provider.downcase}">#@html</div>
|
19
|
+
HTML
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Prismic
|
2
|
+
module Fragments
|
3
|
+
class Image
|
4
|
+
attr_accessor :main, :views
|
5
|
+
|
6
|
+
def initialize(main, views)
|
7
|
+
@main = main
|
8
|
+
@views = views
|
9
|
+
end
|
10
|
+
|
11
|
+
def as_html(link_resolver=nil)
|
12
|
+
main.as_html(link_resolver)
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_view(key)
|
16
|
+
if key == 'main'
|
17
|
+
main
|
18
|
+
elsif @views.has_key?(key)
|
19
|
+
views[key]
|
20
|
+
else
|
21
|
+
raise ViewDoesNotExistException
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ViewDoesNotExistException < Error ; end
|
26
|
+
|
27
|
+
class View
|
28
|
+
attr_accessor :url, :width, :height
|
29
|
+
|
30
|
+
def initialize(url, width, height)
|
31
|
+
@url = url
|
32
|
+
@width = width
|
33
|
+
@height = height
|
34
|
+
end
|
35
|
+
|
36
|
+
def ratio
|
37
|
+
return @width / @height
|
38
|
+
end
|
39
|
+
|
40
|
+
def as_html(link_resolver=nil)
|
41
|
+
%(<img src="#@url" width="#@width" height="#@height" />)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Prismic
|
2
|
+
module Fragments
|
3
|
+
class Link
|
4
|
+
def as_html(link_resolver=nil)
|
5
|
+
%(<a href="#@url">#@url</a>)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class WebLink < Link
|
10
|
+
attr_accessor :url
|
11
|
+
|
12
|
+
def initialize(url)
|
13
|
+
@url = url
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class MediaLink < Link
|
18
|
+
attr_accessor :url
|
19
|
+
|
20
|
+
def initialize(url)
|
21
|
+
@url = url
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class DocumentLink < Link
|
26
|
+
attr_accessor :id, :link_type, :tags, :slug, :broken
|
27
|
+
|
28
|
+
def initialize(id, link_type, tags, slug, broken)
|
29
|
+
@id = id
|
30
|
+
@link_type = link_type
|
31
|
+
@tags = tags
|
32
|
+
@slug = slug
|
33
|
+
@broken = broken
|
34
|
+
end
|
35
|
+
|
36
|
+
def as_html(link_resolver)
|
37
|
+
if broken?
|
38
|
+
%(<span>#{slug}</span>)
|
39
|
+
else
|
40
|
+
%(<a href="#{link_resolver.link_to(self)}">#{slug}</a>)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
alias :broken? :broken
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Prismic
|
2
|
+
module Fragments
|
3
|
+
class Multiple
|
4
|
+
attr_reader :fragments
|
5
|
+
|
6
|
+
def initialize(fragments=[])
|
7
|
+
@fragments = fragments
|
8
|
+
end
|
9
|
+
|
10
|
+
def size
|
11
|
+
@fragments.size
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](i)
|
15
|
+
@fragments[i]
|
16
|
+
end
|
17
|
+
|
18
|
+
def push(fragment)
|
19
|
+
@fragments.push(fragment)
|
20
|
+
end
|
21
|
+
|
22
|
+
def as_html(link_resolver)
|
23
|
+
@fragments.map { |f| f.as_html(link_resolver) }.join
|
24
|
+
end
|
25
|
+
|
26
|
+
alias :length :size
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Prismic
|
2
|
+
module Fragments
|
3
|
+
class Number
|
4
|
+
attr_accessor :value
|
5
|
+
|
6
|
+
def initialize(value)
|
7
|
+
@value = value
|
8
|
+
end
|
9
|
+
|
10
|
+
def as_int
|
11
|
+
@value.to_int
|
12
|
+
end
|
13
|
+
|
14
|
+
def as_html(link_resolver=nil)
|
15
|
+
%(<span class="number">#@value</span>)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
module Prismic
|
2
|
+
module Fragments
|
3
|
+
class StructuredText
|
4
|
+
class Group
|
5
|
+
attr_reader :kind, :blocks
|
6
|
+
def initialize(kind)
|
7
|
+
@kind = kind
|
8
|
+
@blocks = []
|
9
|
+
end
|
10
|
+
def <<(block)
|
11
|
+
blocks << block
|
12
|
+
end
|
13
|
+
end
|
14
|
+
attr_accessor :blocks
|
15
|
+
|
16
|
+
def initialize(blocks)
|
17
|
+
@blocks = blocks
|
18
|
+
end
|
19
|
+
|
20
|
+
def as_html(link_resolver)
|
21
|
+
block_group = ->(block){
|
22
|
+
case block
|
23
|
+
when Block::ListItem
|
24
|
+
block.ordered? ? "ol" : "ul"
|
25
|
+
else
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
}
|
29
|
+
groups, last = [], nil
|
30
|
+
blocks.each {|block|
|
31
|
+
group = block_group.(block)
|
32
|
+
groups << Group.new(group) if !last || group != last
|
33
|
+
groups.last << block
|
34
|
+
last = group
|
35
|
+
}
|
36
|
+
groups.map{|group|
|
37
|
+
html = group.blocks.map{|b| b.as_html(link_resolver) }.join
|
38
|
+
case group.kind
|
39
|
+
when "ol"
|
40
|
+
%(<ol>#{html}</ol>)
|
41
|
+
when "ul"
|
42
|
+
%(<ul>#{html}</ul>)
|
43
|
+
else
|
44
|
+
html
|
45
|
+
end
|
46
|
+
}.join("\n\n")
|
47
|
+
end
|
48
|
+
|
49
|
+
class Span
|
50
|
+
attr_accessor :start, :end
|
51
|
+
|
52
|
+
def initialize(start, finish)
|
53
|
+
@start = start
|
54
|
+
@end = finish
|
55
|
+
end
|
56
|
+
|
57
|
+
class Em < Span
|
58
|
+
def start_html(link_resolver=nil)
|
59
|
+
"<em>"
|
60
|
+
end
|
61
|
+
def end_html(link_resolver=nil)
|
62
|
+
"</em>"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Strong < Span
|
67
|
+
def start_html(link_resolver=nil)
|
68
|
+
"<b>"
|
69
|
+
end
|
70
|
+
def end_html(link_resolver=nil)
|
71
|
+
"</b>"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Hyperlink < Span
|
76
|
+
attr_accessor :link
|
77
|
+
def initialize(start, finish, link)
|
78
|
+
super(start, finish)
|
79
|
+
@link = link
|
80
|
+
end
|
81
|
+
def start_html(link_resolver)
|
82
|
+
# Quick-and-dirty way to generate the right <a> tag
|
83
|
+
link.as_html(link_resolver).sub(/(<a[^>]+>).*/, '\1')
|
84
|
+
end
|
85
|
+
def end_html(link_resolver=nil)
|
86
|
+
"</a>"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class Block
|
92
|
+
class Text
|
93
|
+
attr_accessor :text, :spans
|
94
|
+
|
95
|
+
def initialize(text, spans)
|
96
|
+
@text = text
|
97
|
+
@spans = spans
|
98
|
+
end
|
99
|
+
|
100
|
+
def as_html(link_resolver=nil)
|
101
|
+
start_spans, end_spans = prepare_spans
|
102
|
+
text.chars.each_with_index.map {|c, i|
|
103
|
+
opening = start_spans[i].map {|span|
|
104
|
+
span.start_html(link_resolver)
|
105
|
+
}
|
106
|
+
closing = end_spans[i].map {|span|
|
107
|
+
span.end_html(link_resolver)
|
108
|
+
}
|
109
|
+
opening + closing + [c]
|
110
|
+
}.flatten.join("")
|
111
|
+
end
|
112
|
+
|
113
|
+
def prepare_spans
|
114
|
+
unless defined?(@prepared_spans)
|
115
|
+
start_spans = Hash.new{|h,k| h[k] = [] }
|
116
|
+
end_spans = Hash.new{|h,k| h[k] = [] }
|
117
|
+
spans.each {|span|
|
118
|
+
start_spans[span.start] << span
|
119
|
+
end_spans[span.end] << span
|
120
|
+
}
|
121
|
+
@start_spans = start_spans
|
122
|
+
@end_spans = end_spans
|
123
|
+
end
|
124
|
+
[@start_spans, @end_spans]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Heading < Text
|
129
|
+
attr_accessor :level
|
130
|
+
|
131
|
+
def initialize(text, spans, level)
|
132
|
+
super(text, spans)
|
133
|
+
@level = level
|
134
|
+
end
|
135
|
+
|
136
|
+
def as_html(link_resolver=nil)
|
137
|
+
%(<h#{level}>#{super}</h#{level}>)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class Paragraph < Text
|
142
|
+
def as_html(link_resolver=nil)
|
143
|
+
%(<p>#{super}</p>)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class ListItem < Text
|
148
|
+
attr_accessor :ordered
|
149
|
+
alias :ordered? :ordered
|
150
|
+
|
151
|
+
def initialize(text, spans, ordered)
|
152
|
+
super(text, spans)
|
153
|
+
@ordered = ordered
|
154
|
+
end
|
155
|
+
|
156
|
+
def as_html(link_resolver)
|
157
|
+
%(<li>#{super}</li>)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class Image < Block
|
162
|
+
attr_accessor :view
|
163
|
+
|
164
|
+
def initialize(view)
|
165
|
+
@view = view
|
166
|
+
end
|
167
|
+
|
168
|
+
def url
|
169
|
+
@view.url
|
170
|
+
end
|
171
|
+
|
172
|
+
def width
|
173
|
+
@view.width
|
174
|
+
end
|
175
|
+
|
176
|
+
def height
|
177
|
+
@view.height
|
178
|
+
end
|
179
|
+
|
180
|
+
def as_html(link_resolver)
|
181
|
+
view.as_html(link_resolver)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class Embed < Block
|
186
|
+
|
187
|
+
def initialize(embed)
|
188
|
+
@embed
|
189
|
+
end
|
190
|
+
|
191
|
+
def as_html(link_resolver)
|
192
|
+
embed.as_html(link_resolver)
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
module Prismic
|
2
|
+
module JsonParser
|
3
|
+
class << self
|
4
|
+
def parsers
|
5
|
+
@parsers ||= {
|
6
|
+
'Link.document' => method(:document_link_parser),
|
7
|
+
'Text' => method(:text_parser),
|
8
|
+
'Link.web' => method(:web_link_parser),
|
9
|
+
'Date' => method(:date_parser),
|
10
|
+
'Number' => method(:number_parser),
|
11
|
+
'Embed' => method(:embed_parser),
|
12
|
+
'Image' => method(:image_parser),
|
13
|
+
'Color' => method(:color_parser),
|
14
|
+
'StructuredText' => method(:structured_text_parser),
|
15
|
+
'Select' => method(:select_parser),
|
16
|
+
'Multiple' => method(:multiple_parser),
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def document_link_parser(json)
|
21
|
+
Prismic::Fragments::DocumentLink.new(
|
22
|
+
json['value']['document']['id'],
|
23
|
+
json['value']['document']['type'],
|
24
|
+
json['value']['document']['tags'],
|
25
|
+
json['value']['document']['slug'],
|
26
|
+
json['value']['isBroken'])
|
27
|
+
end
|
28
|
+
|
29
|
+
def text_parser(json)
|
30
|
+
Prismic::Fragments::Text.new(json['value'])
|
31
|
+
end
|
32
|
+
|
33
|
+
def select_parser(json)
|
34
|
+
Prismic::Fragments::Text.new(json['value'])
|
35
|
+
end
|
36
|
+
|
37
|
+
def web_link_parser(json)
|
38
|
+
Prismic::Fragments::WebLink.new(json['value']['url'])
|
39
|
+
end
|
40
|
+
|
41
|
+
def date_parser(json)
|
42
|
+
Prismic::Fragments::Date.new(Time.parse(json['value']))
|
43
|
+
end
|
44
|
+
|
45
|
+
def number_parser(json)
|
46
|
+
Prismic::Fragments::Number.new(json['value'])
|
47
|
+
end
|
48
|
+
|
49
|
+
def embed_parser(json)
|
50
|
+
Prismic::Fragments::Embed.new(
|
51
|
+
json['value']['oembed']['type'],
|
52
|
+
json['value']['oembed']['provider_name'],
|
53
|
+
json['value']['oembed']['provider_url'],
|
54
|
+
json['value']['oembed']['html'],
|
55
|
+
json['value']['oembed']
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def image_parser(json)
|
60
|
+
def self.view_parser(json)
|
61
|
+
Prismic::Fragments::Image::View.new(json['url'],
|
62
|
+
json['dimensions']['width'],
|
63
|
+
json['dimensions']['height'])
|
64
|
+
end
|
65
|
+
|
66
|
+
main = view_parser(json['value']['main'])
|
67
|
+
views = json['value']['views'].map do |name, view|
|
68
|
+
view_parser(view)
|
69
|
+
end
|
70
|
+
|
71
|
+
Prismic::Fragments::Image.new(main, views)
|
72
|
+
end
|
73
|
+
|
74
|
+
def color_parser(json)
|
75
|
+
Prismic::Fragments::Color.new(json['value'][1..6])
|
76
|
+
end
|
77
|
+
|
78
|
+
def structured_text_parser(json)
|
79
|
+
def self.span_parser(span)
|
80
|
+
case span['type']
|
81
|
+
when 'em'
|
82
|
+
Prismic::Fragments::StructuredText::Span::Em.new(span['start'], span['end'])
|
83
|
+
when 'strong'
|
84
|
+
Prismic::Fragments::StructuredText::Span::Strong.new(span['start'], span['end'])
|
85
|
+
when 'hyperlink'
|
86
|
+
Prismic::Fragments::StructuredText::Span::Hyperlink.new(span['start'], span['end'], link_parser(span['data']))
|
87
|
+
else
|
88
|
+
puts "Unknown span_parser type: #{span['type']}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
blocks = json['value'].map do |block|
|
93
|
+
case block['type']
|
94
|
+
when 'paragraph'
|
95
|
+
spans = block['spans'].map {|span| span_parser(span) }
|
96
|
+
Prismic::Fragments::StructuredText::Block::Paragraph.new(block['text'], spans)
|
97
|
+
when /^heading/
|
98
|
+
spans = block['spans'].map {|span| span_parser(span) }
|
99
|
+
Prismic::Fragments::StructuredText::Block::Heading.new(
|
100
|
+
block['text'],
|
101
|
+
spans,
|
102
|
+
block['type'][-1].to_i
|
103
|
+
)
|
104
|
+
when 'o-list-item'
|
105
|
+
spans = block['spans'].map {|span| span_parser(span) }
|
106
|
+
Prismic::Fragments::StructuredText::Block::ListItem.new(
|
107
|
+
block['text'],
|
108
|
+
spans,
|
109
|
+
true # ordered
|
110
|
+
)
|
111
|
+
when 'list-item'
|
112
|
+
spans = block['spans'].map {|span| span_parser(span) }
|
113
|
+
Prismic::Fragments::StructuredText::Block::ListItem.new(
|
114
|
+
block['text'],
|
115
|
+
spans,
|
116
|
+
false # unordered
|
117
|
+
)
|
118
|
+
when 'image'
|
119
|
+
view = Prismic::Fragments::Image::View.new(
|
120
|
+
block['url'],
|
121
|
+
block['dimensions']['width'],
|
122
|
+
block['dimensions']['height']
|
123
|
+
)
|
124
|
+
Prismic::Fragments::StructuredText::Block::Image.new(view)
|
125
|
+
when 'embed'
|
126
|
+
embed = Prismic::Fragments::Embed.new(
|
127
|
+
block['oembed']['type'],
|
128
|
+
block['oembed']['provider_name'],
|
129
|
+
block['oembed']['provider_url'],
|
130
|
+
block['oembed']['html'],
|
131
|
+
block['oembed']
|
132
|
+
)
|
133
|
+
Prismic::Fragments::StructuredText::Block::Image.new(embed)
|
134
|
+
else
|
135
|
+
puts "Unknown bloc type: #{block['type']}"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
Prismic::Fragments::StructuredText.new(blocks)
|
139
|
+
end
|
140
|
+
|
141
|
+
def multiple_parser(json)
|
142
|
+
fragments = json.map do |fragment|
|
143
|
+
parsers[fragment['type']].call(fragment)
|
144
|
+
end
|
145
|
+
Prismic::Fragments::Multiple.new(fragments)
|
146
|
+
end
|
147
|
+
|
148
|
+
def document_parser(json)
|
149
|
+
fragments = Hash[json['data'].values.first.map do |name, fragment|
|
150
|
+
if fragment.is_a? Array
|
151
|
+
[name, multiple_parser(fragment)]
|
152
|
+
else
|
153
|
+
[name, parsers[fragment['type']].call(fragment)]
|
154
|
+
end
|
155
|
+
end]
|
156
|
+
|
157
|
+
Prismic::Document.new(json['id'], json['type'], json['href'], json['tags'],
|
158
|
+
json['slugs'], fragments)
|
159
|
+
end
|
160
|
+
|
161
|
+
private
|
162
|
+
|
163
|
+
private
|
164
|
+
|
165
|
+
def link_parser(json)
|
166
|
+
if json['type'] == 'Link.document'
|
167
|
+
document_link_parser(json)
|
168
|
+
elsif json['type'] == 'Link.web'
|
169
|
+
web_link_parser(json)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|