prismic.io 1.0.0.rc10 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/Changelog.md +7 -0
- data/Gemfile.lock +1 -1
- data/lib/prismic/cache/basic.rb +5 -5
- data/lib/prismic/fragments/embed.rb +1 -1
- data/lib/prismic/fragments/structured_text.rb +141 -67
- data/lib/prismic/json_parsers.rb +11 -7
- data/lib/prismic/version.rb +1 -1
- data/lib/prismic.rb +14 -0
- data/prismic.gemspec +1 -1
- data/spec/cache_spec.rb +6 -6
- data/spec/fragments_spec.rb +19 -11
- data/spec/json_parsers_spec.rb +34 -3
- data/spec/lesbonneschoses_spec.rb +53 -2
- data/spec/prismic_spec.rb +2 -1
- data/spec/responses_mocks/structured_text_paragraph.json +29 -28
- data/spec/responses_mocks/structured_text_with_labels.json +156 -0
- data/spec/spec_helper.rb +5 -0
- metadata +21 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8622f78a1a654d406af4edf4471810ab14e0a4a2
|
4
|
+
data.tar.gz: 3861bfec9717d19b0e047d86f4e28375b6f801d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 962b52cb0b6fa39f30058653bbbc99e44d33be0516a30afd6a8ba3c7cae6ff1ef1643da2818e8eaa1cde8e751f532b4c881f83e75f0e929a6846a36da2e0c2f2
|
7
|
+
data.tar.gz: 004429336746943544191ae573d28fddd03dc8147292020ca4a7836fddc6d47f2748384f86004070463f8ab15b331bae88561792f8577a279121120395532da0
|
data/Changelog.md
ADDED
data/Gemfile.lock
CHANGED
data/lib/prismic/cache/basic.rb
CHANGED
@@ -6,7 +6,7 @@ module Prismic
|
|
6
6
|
attr_reader :expired_in
|
7
7
|
attr_reader :data
|
8
8
|
|
9
|
-
def initialize(data, expired_in
|
9
|
+
def initialize(data, expired_in)
|
10
10
|
@data = data
|
11
11
|
@expired_in = expired_in
|
12
12
|
end
|
@@ -26,9 +26,9 @@ module Prismic
|
|
26
26
|
include?(key) ? @cache[key].data : nil
|
27
27
|
end
|
28
28
|
|
29
|
-
def set(key, value = nil, expired_in =
|
29
|
+
def set(key, value = nil, expired_in = nil)
|
30
30
|
data = block_given? ? yield : value
|
31
|
-
expired_in =
|
31
|
+
expired_in = expired_in && Time.now.getutc.to_i + expired_in
|
32
32
|
entry = BasicCacheEntry.new(data, expired_in)
|
33
33
|
@cache[key] = entry
|
34
34
|
entry.data
|
@@ -38,7 +38,7 @@ module Prismic
|
|
38
38
|
@cache.keys.include?(key)
|
39
39
|
end
|
40
40
|
|
41
|
-
def get_or_set(key, value = nil, expired_in =
|
41
|
+
def get_or_set(key, value = nil, expired_in = nil)
|
42
42
|
return get(key) if include?(key) && !expired?(key)
|
43
43
|
set(key, block_given? ? yield : value, expired_in)
|
44
44
|
end
|
@@ -51,7 +51,7 @@ module Prismic
|
|
51
51
|
def expired?(key)
|
52
52
|
if include?(key)
|
53
53
|
expired_in = @cache[key].expired_in
|
54
|
-
|
54
|
+
expired_in && expired_in < Time.now.getutc.to_i
|
55
55
|
else
|
56
56
|
false
|
57
57
|
end
|
@@ -18,7 +18,7 @@ module Prismic
|
|
18
18
|
# application's specific URL
|
19
19
|
#
|
20
20
|
# @return [String] the HTML representation
|
21
|
-
def as_html(link_resolver=nil)
|
21
|
+
def as_html(link_resolver=nil, html_serializer=nil)
|
22
22
|
<<-HTML
|
23
23
|
<div data-oembed="#@url"
|
24
24
|
data-oembed-type="#{@embed_type.downcase}"
|
@@ -31,7 +31,7 @@ module Prismic
|
|
31
31
|
# it is not advised to override this method if you want to change the HTML output, you should
|
32
32
|
# override the as_html method at the block level (like {Heading.as_html}, or {Preformatted.as_html},
|
33
33
|
# for instance).
|
34
|
-
def as_html(link_resolver)
|
34
|
+
def as_html(link_resolver, html_serializer=nil)
|
35
35
|
# Defining blocks that deserve grouping, assigning them "group kind" names
|
36
36
|
block_group = ->(block){
|
37
37
|
case block
|
@@ -52,7 +52,9 @@ module Prismic
|
|
52
52
|
# HTML-serializing the groups object (delegating the serialization of Block objects),
|
53
53
|
# without forgetting to frame the BlockGroup objects right if needed
|
54
54
|
groups.map{|group|
|
55
|
-
html = group.blocks.map{|b|
|
55
|
+
html = group.blocks.map { |b|
|
56
|
+
b.as_html(link_resolver, html_serializer)
|
57
|
+
}.join
|
56
58
|
case group.kind
|
57
59
|
when "ol"
|
58
60
|
%(<ol>#{html}</ol>)
|
@@ -96,21 +98,26 @@ module Prismic
|
|
96
98
|
@end = finish
|
97
99
|
end
|
98
100
|
|
99
|
-
class
|
100
|
-
|
101
|
-
|
101
|
+
class Label < Span
|
102
|
+
attr_accessor :label
|
103
|
+
def initialize(start, finish, label)
|
104
|
+
super(start, finish)
|
105
|
+
@label = label
|
102
106
|
end
|
103
|
-
def
|
104
|
-
"</
|
107
|
+
def serialize(text, link_resolver = nil)
|
108
|
+
"<span class=\"#{@label}\">#{text}</span>"
|
105
109
|
end
|
106
110
|
end
|
107
111
|
|
108
|
-
class
|
109
|
-
def
|
110
|
-
"<
|
112
|
+
class Em < Span
|
113
|
+
def serialize(text, link_resolver = nil)
|
114
|
+
"<em>#{text}</em>"
|
111
115
|
end
|
112
|
-
|
113
|
-
|
116
|
+
end
|
117
|
+
|
118
|
+
class Strong < Span
|
119
|
+
def serialize(text, link_resolver = nil)
|
120
|
+
"<strong>#{text}</strong>"
|
114
121
|
end
|
115
122
|
end
|
116
123
|
|
@@ -120,13 +127,15 @@ module Prismic
|
|
120
127
|
super(start, finish)
|
121
128
|
@link = link
|
122
129
|
end
|
123
|
-
def
|
124
|
-
link.
|
125
|
-
|
126
|
-
|
127
|
-
|
130
|
+
def serialize(text, link_resolver = nil)
|
131
|
+
if link.is_a? Prismic::Fragments::DocumentLink and link.broken
|
132
|
+
"<span>#{text}</span>"
|
133
|
+
else
|
134
|
+
%(<a href="#{link.url(link_resolver)}">#{text}</a>)
|
135
|
+
end
|
128
136
|
end
|
129
137
|
end
|
138
|
+
|
130
139
|
end
|
131
140
|
|
132
141
|
class Block
|
@@ -140,45 +149,55 @@ module Prismic
|
|
140
149
|
end
|
141
150
|
|
142
151
|
class Text
|
143
|
-
attr_accessor :text, :spans
|
152
|
+
attr_accessor :text, :spans, :label
|
144
153
|
|
145
|
-
def initialize(text, spans)
|
154
|
+
def initialize(text, spans, label = nil)
|
146
155
|
@text = text
|
147
156
|
@spans = spans.select{|span| span.start < span.end}
|
157
|
+
@label = label
|
148
158
|
end
|
149
159
|
|
150
|
-
def
|
160
|
+
def class_code
|
161
|
+
(@label && %( class="#{label}")) || ''
|
162
|
+
end
|
163
|
+
|
164
|
+
def as_html(link_resolver=nil, html_serializer=nil)
|
165
|
+
html = ''
|
151
166
|
# Getting Hashes of spanning tags to insert, sorted by starting position, and by ending position
|
152
167
|
start_spans, end_spans = prepare_spans
|
153
|
-
#
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
168
|
+
# Open tags
|
169
|
+
stack = Array.new
|
170
|
+
(text.length + 1).times do |pos| # Looping to length + 1 to catch closing tags
|
171
|
+
end_spans[pos].each do |t|
|
172
|
+
# Close a tag
|
173
|
+
tag = stack.pop
|
174
|
+
inner_html = serialize(tag[:span], tag[:html], link_resolver, html_serializer)
|
175
|
+
if stack.empty?
|
176
|
+
# The tag was top-level
|
177
|
+
html += inner_html
|
178
|
+
else
|
179
|
+
# Add the content to the parent tag
|
180
|
+
stack[-1][:html] += inner_html
|
181
|
+
end
|
182
|
+
end
|
183
|
+
start_spans[pos].each do |tag|
|
184
|
+
# Open a tag
|
185
|
+
stack.push({
|
186
|
+
:span => tag,
|
187
|
+
:html => ''
|
188
|
+
})
|
189
|
+
end
|
190
|
+
if pos < text.length
|
191
|
+
if stack.empty?
|
192
|
+
# Top level text
|
193
|
+
html += CGI::escapeHTML(text[pos])
|
194
|
+
else
|
195
|
+
# Inner text of a span
|
196
|
+
stack[-1][:html] += CGI::escapeHTML(text[pos])
|
197
|
+
end
|
198
|
+
end
|
174
199
|
end
|
175
|
-
|
176
|
-
# Inserting what's left of the string, if there is something
|
177
|
-
output << text[cursor..-1]
|
178
|
-
|
179
|
-
# Making the array into a string
|
180
|
-
output.join
|
181
|
-
|
200
|
+
html
|
182
201
|
end
|
183
202
|
|
184
203
|
# Building two span Hashes:
|
@@ -192,7 +211,8 @@ module Prismic
|
|
192
211
|
start_spans[span.start] << span
|
193
212
|
end_spans[span.end] << span
|
194
213
|
}
|
195
|
-
|
214
|
+
# Make sure the spans are sorted bigger first to respect the hierarchy
|
215
|
+
@start_spans = start_spans.each { |_, spans| spans.sort! { |a, b| b.end - b.start <=> a.end - a.start } }
|
196
216
|
@end_spans = end_spans
|
197
217
|
end
|
198
218
|
[@start_spans, @end_spans]
|
@@ -204,30 +224,56 @@ module Prismic
|
|
204
224
|
def as_text
|
205
225
|
@text
|
206
226
|
end
|
227
|
+
|
228
|
+
def serialize(elt, text, link_resolver, html_serializer)
|
229
|
+
custom_html = html_serializer && html_serializer.serialize(elt, text)
|
230
|
+
if custom_html.nil?
|
231
|
+
elt.serialize(text, link_resolver)
|
232
|
+
else
|
233
|
+
custom_html
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
private :class_code
|
207
238
|
end
|
208
239
|
|
209
240
|
class Heading < Text
|
210
241
|
attr_accessor :level
|
211
242
|
|
212
|
-
def initialize(text, spans, level)
|
243
|
+
def initialize(text, spans, level, label = nil)
|
213
244
|
super(text, spans)
|
214
245
|
@level = level
|
215
246
|
end
|
216
247
|
|
217
|
-
def as_html(link_resolver=nil)
|
218
|
-
|
248
|
+
def as_html(link_resolver=nil, html_serializer=nil)
|
249
|
+
custom_html = html_serializer && html_serializer.serialize(self, super)
|
250
|
+
if custom_html.nil?
|
251
|
+
%(<h#{level}#{class_code}>#{super}</h#{level}>)
|
252
|
+
else
|
253
|
+
custom_html
|
254
|
+
end
|
219
255
|
end
|
220
256
|
end
|
221
257
|
|
222
258
|
class Paragraph < Text
|
223
|
-
def as_html(link_resolver=nil)
|
224
|
-
|
259
|
+
def as_html(link_resolver=nil, html_serializer=nil)
|
260
|
+
custom_html = html_serializer && html_serializer.serialize(self, super)
|
261
|
+
if custom_html.nil?
|
262
|
+
%(<p#{class_code}>#{super}</p>)
|
263
|
+
else
|
264
|
+
custom_html
|
265
|
+
end
|
225
266
|
end
|
226
267
|
end
|
227
268
|
|
228
269
|
class Preformatted < Text
|
229
|
-
def as_html(link_resolver=nil)
|
230
|
-
|
270
|
+
def as_html(link_resolver=nil, html_serializer=nil)
|
271
|
+
custom_html = html_serializer && html_serializer.serialize(self, super)
|
272
|
+
if custom_html.nil?
|
273
|
+
%(<pre#{class_code}>#{super}</pre>)
|
274
|
+
else
|
275
|
+
custom_html
|
276
|
+
end
|
231
277
|
end
|
232
278
|
end
|
233
279
|
|
@@ -235,21 +281,27 @@ module Prismic
|
|
235
281
|
attr_accessor :ordered
|
236
282
|
alias :ordered? :ordered
|
237
283
|
|
238
|
-
def initialize(text, spans, ordered)
|
284
|
+
def initialize(text, spans, ordered, label = nil)
|
239
285
|
super(text, spans)
|
240
286
|
@ordered = ordered
|
241
287
|
end
|
242
288
|
|
243
|
-
def as_html(link_resolver)
|
244
|
-
|
289
|
+
def as_html(link_resolver, html_serializer=nil)
|
290
|
+
custom_html = html_serializer && html_serializer.serialize(self, super)
|
291
|
+
if custom_html.nil?
|
292
|
+
%(<li#{class_code}>#{super}</li>)
|
293
|
+
else
|
294
|
+
custom_html
|
295
|
+
end
|
245
296
|
end
|
246
297
|
end
|
247
298
|
|
248
299
|
class Image < Block
|
249
|
-
attr_accessor :view
|
300
|
+
attr_accessor :view, :label
|
250
301
|
|
251
|
-
def initialize(view)
|
302
|
+
def initialize(view, label = nil)
|
252
303
|
@view = view
|
304
|
+
@label = label
|
253
305
|
end
|
254
306
|
|
255
307
|
def url
|
@@ -276,19 +328,41 @@ module Prismic
|
|
276
328
|
@view.link_to
|
277
329
|
end
|
278
330
|
|
279
|
-
def as_html(link_resolver)
|
280
|
-
|
331
|
+
def as_html(link_resolver, html_serializer = nil)
|
332
|
+
custom = nil
|
333
|
+
unless html_serializer.nil?
|
334
|
+
custom = html_serializer.serialize(self, '')
|
335
|
+
end
|
336
|
+
if custom.nil?
|
337
|
+
classes = ['block-img']
|
338
|
+
unless @label.nil?
|
339
|
+
classes.push(@label)
|
340
|
+
end
|
341
|
+
%(<p class="#{classes.join(' ')}">#{view.as_html(link_resolver)}</p>)
|
342
|
+
else
|
343
|
+
custom
|
344
|
+
end
|
281
345
|
end
|
282
346
|
end
|
283
347
|
|
284
348
|
class Embed < Block
|
349
|
+
attr_accessor :label
|
285
350
|
|
286
|
-
def initialize(embed)
|
287
|
-
@embed
|
351
|
+
def initialize(embed, label)
|
352
|
+
@embed = embed
|
353
|
+
@label = label
|
288
354
|
end
|
289
355
|
|
290
|
-
def as_html(link_resolver)
|
291
|
-
|
356
|
+
def as_html(link_resolver, html_serializer = nil)
|
357
|
+
custom = nil
|
358
|
+
unless html_serializer.nil?
|
359
|
+
custom = html_serializer.serialize(self, '')
|
360
|
+
end
|
361
|
+
if custom.nil?
|
362
|
+
embed.as_html(link_resolver)
|
363
|
+
else
|
364
|
+
custom
|
365
|
+
end
|
292
366
|
end
|
293
367
|
|
294
368
|
end
|
data/lib/prismic/json_parsers.rb
CHANGED
@@ -117,7 +117,8 @@ module Prismic
|
|
117
117
|
when 'hyperlink'
|
118
118
|
Prismic::Fragments::StructuredText::Span::Hyperlink.new(span['start'], span['end'], link_parser(span['data']))
|
119
119
|
else
|
120
|
-
|
120
|
+
label = span['data'] && span['data']['label']
|
121
|
+
Prismic::Fragments::StructuredText::Span::Label.new(span['start'], span['end'], label)
|
121
122
|
end
|
122
123
|
end
|
123
124
|
|
@@ -125,31 +126,34 @@ module Prismic
|
|
125
126
|
case block['type']
|
126
127
|
when 'paragraph'
|
127
128
|
spans = block['spans'].map {|span| span_parser(span) }
|
128
|
-
Prismic::Fragments::StructuredText::Block::Paragraph.new(block['text'], spans)
|
129
|
+
Prismic::Fragments::StructuredText::Block::Paragraph.new(block['text'], spans, block['label'])
|
129
130
|
when 'preformatted'
|
130
131
|
spans = block['spans'].map {|span| span_parser(span) }
|
131
|
-
Prismic::Fragments::StructuredText::Block::Preformatted.new(block['text'], spans)
|
132
|
+
Prismic::Fragments::StructuredText::Block::Preformatted.new(block['text'], spans, block['label'])
|
132
133
|
when /^heading(\d+)$/
|
133
134
|
heading = $1
|
134
135
|
spans = block['spans'].map {|span| span_parser(span) }
|
135
136
|
Prismic::Fragments::StructuredText::Block::Heading.new(
|
136
137
|
block['text'],
|
137
138
|
spans,
|
138
|
-
heading.to_i
|
139
|
+
heading.to_i,
|
140
|
+
block['label']
|
139
141
|
)
|
140
142
|
when 'o-list-item'
|
141
143
|
spans = block['spans'].map {|span| span_parser(span) }
|
142
144
|
Prismic::Fragments::StructuredText::Block::ListItem.new(
|
143
145
|
block['text'],
|
144
146
|
spans,
|
145
|
-
true # ordered
|
147
|
+
true, # ordered
|
148
|
+
block['label']
|
146
149
|
)
|
147
150
|
when 'list-item'
|
148
151
|
spans = block['spans'].map {|span| span_parser(span) }
|
149
152
|
Prismic::Fragments::StructuredText::Block::ListItem.new(
|
150
153
|
block['text'],
|
151
154
|
spans,
|
152
|
-
false # unordered
|
155
|
+
false, # unordered
|
156
|
+
block['label']
|
153
157
|
)
|
154
158
|
when 'image'
|
155
159
|
view = Prismic::Fragments::Image::View.new(
|
@@ -160,7 +164,7 @@ module Prismic
|
|
160
164
|
block['copyright'],
|
161
165
|
block['linkTo'] ? link_parser(block['linkTo']) : nil
|
162
166
|
)
|
163
|
-
Prismic::Fragments::StructuredText::Block::Image.new(view)
|
167
|
+
Prismic::Fragments::StructuredText::Block::Image.new(view, block['label'])
|
164
168
|
when 'embed'
|
165
169
|
boembed = block['oembed']
|
166
170
|
Prismic::Fragments::Embed.new(
|
data/lib/prismic/version.rb
CHANGED
data/lib/prismic.rb
CHANGED
@@ -520,6 +520,16 @@ module Prismic
|
|
520
520
|
end
|
521
521
|
end
|
522
522
|
|
523
|
+
class HtmlSerializer
|
524
|
+
def initialize(&blk)
|
525
|
+
@blk = blk
|
526
|
+
end
|
527
|
+
|
528
|
+
def serialize(element, content)
|
529
|
+
@blk.call(element, content)
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
523
533
|
# Default HTTP client implementation, using the standard Net::HTTP library.
|
524
534
|
module DefaultHTTPClient
|
525
535
|
class << self
|
@@ -586,6 +596,10 @@ module Prismic
|
|
586
596
|
LinkResolver.new(ref, &blk)
|
587
597
|
end
|
588
598
|
|
599
|
+
def self.html_serializer(&blk)
|
600
|
+
HtmlSerializer.new(&blk)
|
601
|
+
end
|
602
|
+
|
589
603
|
end
|
590
604
|
|
591
605
|
require 'prismic/api'
|
data/prismic.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'prismic/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "prismic.io"
|
8
8
|
spec.version = Prismic::VERSION
|
9
|
-
spec.authors = ["Étienne Vallette d'Osia", "Samy Dindane", "Rudy Rigot"]
|
9
|
+
spec.authors = ["Étienne Vallette d'Osia", "Erwan Loisant", "Samy Dindane", "Rudy Rigot"]
|
10
10
|
spec.email = ["evo@zenexity.com"]
|
11
11
|
spec.description = %q{The standard Prismic.io's API library.}
|
12
12
|
spec.summary = %q{Prismic.io development kit}
|
data/spec/cache_spec.rb
CHANGED
@@ -95,17 +95,17 @@ describe "Basic Cache's" do
|
|
95
95
|
|
96
96
|
it 'set with expiration value & get value' do
|
97
97
|
cache = Prismic::BasicCache.new
|
98
|
-
cache.set('key', 'value',
|
99
|
-
sleep(
|
98
|
+
cache.set('key', 'value', 1)
|
99
|
+
sleep(2)
|
100
100
|
cache.get('key').should == nil
|
101
101
|
end
|
102
102
|
|
103
103
|
it 'set with expiration and a block' do
|
104
104
|
cache = Prismic::BasicCache.new
|
105
|
-
cache.get_or_set('key', nil,
|
106
|
-
cache.get_or_set('key', nil,
|
107
|
-
sleep(
|
108
|
-
cache.get_or_set('key', nil,
|
105
|
+
cache.get_or_set('key', nil, 1){ 'value' }
|
106
|
+
cache.get_or_set('key', nil, 1){ 'othervalue' }.should == 'value'
|
107
|
+
sleep(2)
|
108
|
+
cache.get_or_set('key', nil, 1){ 'othervalue' }.should == 'othervalue'
|
109
109
|
end
|
110
110
|
|
111
111
|
it 'set & test value' do
|
data/spec/fragments_spec.rb
CHANGED
@@ -93,7 +93,7 @@ describe 'ImageLink' do
|
|
93
93
|
|
94
94
|
describe 'url' do
|
95
95
|
before do
|
96
|
-
@link_resolver = Prismic.link_resolver(
|
96
|
+
@link_resolver = Prismic.link_resolver('master'){|doc_link| "http://localhost/#{doc_link.id}" }
|
97
97
|
end
|
98
98
|
it 'works in a unified way' do
|
99
99
|
@image_link.url(@link_resolver).should == 'my_url'
|
@@ -109,7 +109,10 @@ describe 'FileLink' do
|
|
109
109
|
@structured_text = Prismic::JsonParser.structured_text_parser(@json_structured_text)
|
110
110
|
end
|
111
111
|
it 'serializes well into HTML' do
|
112
|
-
@structured_text.as_html(nil).should ==
|
112
|
+
@structured_text.as_html(nil).should ==
|
113
|
+
"<p><a href=\"https://prismic-io.s3.amazonaws.com/annual.report.pdf\">2012 Annual Report</a></p>\n\n"\
|
114
|
+
"<p><a href=\"https://prismic-io.s3.amazonaws.com/annual.budget.pdf\">2012 Annual Budget</a></p>\n\n"\
|
115
|
+
"<p><a href=\"https://prismic-io.s3.amazonaws.com/vision.strategic.plan_.sm_.pdf\">2015 Vision & Strategic Plan</a></p>"
|
113
116
|
end
|
114
117
|
end
|
115
118
|
end
|
@@ -122,7 +125,10 @@ describe 'Span' do
|
|
122
125
|
@structured_text = Prismic::JsonParser.structured_text_parser(@json_structured_text)
|
123
126
|
end
|
124
127
|
it 'serializes well into HTML' do
|
125
|
-
@structured_text.as_html(nil).should ==
|
128
|
+
@structured_text.as_html(nil).should ==
|
129
|
+
"<h3><strong>Powering Through 2013 </strong></h3>\n\n"\
|
130
|
+
"<h3><strong>Online Resources:</strong></h3>\n\n"\
|
131
|
+
"<ul><li>Hear more from our executive team as they reflect on 2013 and share their vision for 2014 on our blog <a href=\"http://prismic.io\">here</a></li></ul>"
|
126
132
|
end
|
127
133
|
end
|
128
134
|
describe 'in structured texts when multiple spans' do
|
@@ -132,7 +138,9 @@ describe 'Span' do
|
|
132
138
|
@structured_text = Prismic::JsonParser.structured_text_parser(@json_structured_text)
|
133
139
|
end
|
134
140
|
it 'serializes well into HTML' do
|
135
|
-
@structured_text.as_html(nil).should ==
|
141
|
+
@structured_text.as_html(nil).should ==
|
142
|
+
'<p class="vanilla">Experience <a href="http://prismic.io">the</a> ultimate vanilla experience. '\
|
143
|
+
'Our vanilla Macarons are made with our very own (in-house) <em>pure extract of Madagascar vanilla</em>, and subtly dusted with <strong>our own vanilla sugar</strong> (which we make from real vanilla beans).</p>'
|
136
144
|
end
|
137
145
|
end
|
138
146
|
end
|
@@ -507,17 +515,17 @@ end
|
|
507
515
|
|
508
516
|
describe 'StructuredText::Heading' do
|
509
517
|
before do
|
510
|
-
@text =
|
518
|
+
@text = 'This is a simple test.'
|
511
519
|
@spans = [em(5, 7), strong(8, 9)]
|
512
520
|
end
|
513
521
|
let :block do Prismic::Fragments::StructuredText::Block::Heading.new(@text, @spans, @heading) end
|
514
522
|
it 'generates valid h1 html' do
|
515
523
|
@heading = 1
|
516
|
-
block.as_html(nil).should ==
|
524
|
+
block.as_html(nil).should == '<h1>This <em>is</em> <strong>a</strong> simple test.</h1>'
|
517
525
|
end
|
518
526
|
it 'generates valid h2 html' do
|
519
527
|
@heading = 2
|
520
|
-
block.as_html(nil).should ==
|
528
|
+
block.as_html(nil).should == '<h2>This <em>is</em> <strong>a</strong> simple test.</h2>'
|
521
529
|
end
|
522
530
|
end
|
523
531
|
|
@@ -546,7 +554,7 @@ describe 'StructuredText::Paragraph' do
|
|
546
554
|
it "espaces HTML content (2 spans on the same text)" do
|
547
555
|
@text = 'abcdefghijklmnopqrstuvwxyz'
|
548
556
|
@spans = [em(2, 4), strong(2, 4)]
|
549
|
-
block.as_html(nil).should =~ %r{^<[^>]+>ab<strong
|
557
|
+
block.as_html(nil).should =~ %r{^<[^>]+>ab<em><strong>cd</strong></em>efghijklmnopqrstuvwxyz<[^>]+>$}
|
550
558
|
end
|
551
559
|
it "espaces HTML content (2 spans on the same text - one bigger 1)" do
|
552
560
|
@text = 'abcdefghijklmnopqrstuvwxyz'
|
@@ -626,14 +634,14 @@ describe 'StructuredText::Hyperlink' do
|
|
626
634
|
|
627
635
|
describe 'as_html' do
|
628
636
|
it "can generate valid link" do
|
629
|
-
@hyperlink.
|
637
|
+
@hyperlink.serialize('', @link_resolver).should == '<a href="http://localhost/UdUjvt_mqVNObPeO"></a>'
|
630
638
|
end
|
631
639
|
it "raises an error when no link_resolver provided" do
|
632
|
-
expect { @hyperlink.
|
640
|
+
expect { @hyperlink.serialize('', nil) }.to raise_error
|
633
641
|
end
|
634
642
|
it "can generate valid html for broken link" do
|
635
643
|
@link.broken = true
|
636
|
-
@hyperlink.
|
644
|
+
@hyperlink.serialize('', @link_resolver).should == '<span></span>'
|
637
645
|
end
|
638
646
|
end
|
639
647
|
end
|
data/spec/json_parsers_spec.rb
CHANGED
@@ -221,13 +221,13 @@ describe 'image_parser in StructuredText' do
|
|
221
221
|
|
222
222
|
<p>The following image is linked.</p>
|
223
223
|
|
224
|
-
<a href="http://google.com/"><img src="http://fpoimg.com/129x260" alt="" width="260" height="129" /></a>
|
224
|
+
<p class="block-img"><a href="http://google.com/"><img src="http://fpoimg.com/129x260" alt="" width="260" height="129" /></a></p>
|
225
225
|
|
226
226
|
<p><strong>More important stuff</strong></p>
|
227
227
|
|
228
228
|
<p>One more image, this one is not linked:</p>
|
229
229
|
|
230
|
-
<img src="http://fpoimg.com/199x300" alt="" width="300" height="199"
|
230
|
+
<p class="block-img"><img src="http://fpoimg.com/199x300" alt="" width="300" height="199" /></p>
|
231
231
|
expected
|
232
232
|
expected.chomp!
|
233
233
|
link_resolver = Prismic.link_resolver("master"){|doc_link| "http://localhost/#{doc_link.id}" }
|
@@ -442,8 +442,39 @@ describe 'unknown_parser' do
|
|
442
442
|
@json = JSON.load(@raw_json)
|
443
443
|
end
|
444
444
|
|
445
|
-
it
|
445
|
+
it 'raises the proper error' do
|
446
446
|
Prismic::JsonParser.should_receive(:warn).with("Type blabla is unknown, fragment was skipped; perhaps you should update your prismic.io gem?")
|
447
447
|
Prismic::JsonParser.document_parser(@json).fragments.size.should == 2
|
448
448
|
end
|
449
449
|
end
|
450
|
+
|
451
|
+
describe 'structured_text_label_parser' do
|
452
|
+
before do
|
453
|
+
raw_json = File.read("#{File.dirname(__FILE__)}/responses_mocks/structured_text_with_labels.json")
|
454
|
+
json = JSON.load(raw_json)
|
455
|
+
@structured_text = Prismic::JsonParser.structured_text_parser(json)
|
456
|
+
end
|
457
|
+
|
458
|
+
it 'outputs correctly as HTML' do
|
459
|
+
link_resolver = Prismic.link_resolver("master"){|doc_link| "http://localhost/#{doc_link.id}" }
|
460
|
+
@structured_text.as_html(link_resolver).should ==
|
461
|
+
"<h1>Tips to dress a pastry</h1>\n\n" +
|
462
|
+
"<p class=\"block-img\"><img src=\"https://prismic-io.s3.amazonaws.com/lesbonneschoses-vcerzcwaaohojzo/381f3a78dfe952b229fb49ceaa9926f7009ae20a.jpg\" alt=\"\" width=\"640\" height=\"666\" /></p>\n\n" +
|
463
|
+
"<p>Our Pastry Dressers (yes, it is <a href=\"http://localhost/UlfoxUnM0wkXYXbh\">a full-time job</a> in <em>Les Bonnes Choses</em>!) have it somewhat different from our other pastry artists: while the others keep their main focus on the taste, smell, and potentially touch of your pastries, the Pastry Dressers are mainly focused on their looks.</p>\n\n" +
|
464
|
+
"<p>It sometimes makes them feem like they're doing a job that is reasonably different from plain old pastry, and to make the most of your pastry dressings, perhaps so should you!</p>\n\n" +
|
465
|
+
"<h2>Step by step</h2>\n\n" +
|
466
|
+
"<p>From bottom to top, the steps towards a great dressing are pretty clear, and change rarely.</p>\n\n" +
|
467
|
+
"<h3>Pastry Dresser, or speleologist?</h3>\n\n" +
|
468
|
+
"<p>One of the first handy phases of dressing your pastry will be about carving to get to a desired shape and size to build upon. This is very precise work, as you will need to <span class=\"author\">clean</span> the object without breaking it, to remove pieces of it while keeping intact the meaningful bits. Now you're ready to iterate upon it!</p>\n\n" +
|
469
|
+
"<h3>Pastry Dresser, or clay sculptor?</h3>\n\n<p>" +
|
470
|
+
"Then, you will need to shape your piece of art <span class=\"author\"><strong>into</strong></span> the design you have in mind, by adding the right materials to just the right places. Ganache is your friend in such moments, such as any shape-free material. You'll have to master them, so they obey to the shapes you have in mind.</p>\n\n" +
|
471
|
+
"<h3>Pastry Dresser, or hairdresser?</h3>\n\n" +
|
472
|
+
"<p>The top of the pastry is a priority zone for finalization. This is where your "last touch" goes, and it's tremendously important, as it gives the pastry most of its character. You will have to play with the details, to keep the top of your piece on the... top of your priorities!</p>\n\n<h2>Before starting</h2>\n\n<p>" +
|
473
|
+
"Finishing by the beginning: what did we have to consider, before running towards the aforementioned steps?</p>\n\n" +
|
474
|
+
"<p class=\"block-img\"><img src=\"https://prismic-io.s3.amazonaws.com/lesbonneschoses-vcerzcwaaohojzo/502ebb427b5eb45693800816fc778316c04935f5.jpg\" alt=\"\" width=\"640\" height=\"427\" /></p>\n\n" +
|
475
|
+
"<h3>Pastry Dresser, or illustrator?</h3>\n\n" +
|
476
|
+
"<p>We didn't mention color, but it's a very important component of the piece. Just like an illustrator will pick colors that add to the shape in a matching way to keep a perfect meaning, the colors must be perfect to be consistent with the taste of the piece (do not use green-colored sugar for a strawberry-flavored pastry, if you don't want to gross people out!)</p>\n\n" +
|
477
|
+
"<h3>Pastry Dresser, or designer?</h3>\n\n<p>And even before the illustration and colors, you really need to take the time to think about your destination, to make sure it's nothing short of perfect. This may imply taking the time to sit down for a few minutes with a paper and a pen. The first skill of an imaginative Pastry Dresser is a drawing skill, just like a fashion stylist.</p>"
|
478
|
+
end
|
479
|
+
|
480
|
+
end
|
@@ -121,17 +121,68 @@ describe 'LesBonnesChoses' do
|
|
121
121
|
describe 'Fragments' do
|
122
122
|
before do
|
123
123
|
@link_resolver = Prismic.link_resolver("master"){|doc_link| "http://localhost/#{doc_link.id}" }
|
124
|
+
@html_serializer = Prismic.html_serializer do |element, html|
|
125
|
+
if element.is_a?(Prismic::Fragments::StructuredText::Block::Image)
|
126
|
+
%(<img src="#{element.url}" alt="#{element.alt}" width="#{element.width}" height="#{element.height}" />)
|
127
|
+
else
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
end
|
124
131
|
end
|
125
132
|
describe 'API::Fragments::StructuredText' do
|
126
133
|
it "returns a correct as_html on a StructuredText with list, span, embed and image" do
|
127
134
|
@api.form("everything")
|
128
135
|
.query(%([[:d = at(document.id, "UlfoxUnM0wkXYXbX")]]))
|
129
|
-
.submit(@master_ref)[0]['blog-post.body'].as_html(@link_resolver).gsub("'", "'").should ==
|
136
|
+
.submit(@master_ref)[0]['blog-post.body'].as_html(@link_resolver).gsub("'", "'").should ==
|
137
|
+
"<h1>Get the right approach to ganache</h1>\n\n"\
|
138
|
+
"<p>A lot of people touch base with us to know about one of our key ingredients, and the essential role it plays in our creations: ganache.</p>\n\n"\
|
139
|
+
"<p>Indeed, ganache is the macaron's softener, or else, macarons would be but tough biscuits; it is the cupcake's wrapper, or else, cupcakes would be but plain old cake. We even sometimes use ganache within our cupcakes, to soften the cake itself, or as a support to our pies' content.</p>\n\n"\
|
140
|
+
"<h2>How to approach ganache</h2>\n\n"\
|
141
|
+
"<p class=\"block-img\"><img src=\"https://prismic-io.s3.amazonaws.com/lesbonneschoses/ee7b984b98db4516aba2eabd54ab498293913c6c.jpg\" alt=\"\" width=\"640\" height=\"425\" /></p>\n\n"\
|
142
|
+
"<p>Apart from the taste balance, which is always a challenge when it comes to pastry, the tough part about ganache is about thickness. It is even harder to predict through all the phases the ganache gets to meet (how long will it get melted? how long will it remain in the fridge?). "\
|
143
|
+
"Things get a hell of a lot easier to get once you consider that there are two main ways to get the perfect ganache:</p>\n\n"\
|
144
|
+
"<ul><li><strong>working from the top down</strong>: start with a thick, almost hard material, and soften it by manipulating it, or by mixing it with a more liquid ingredient (like milk)</li>"\
|
145
|
+
"<li><strong>working from the bottom up</strong>: start from a liquid-ish state, and harden it by miwing it with thicker ingredients, or by leaving it in the fridge longer.</li></ul>\n\n"\
|
146
|
+
"<p>We do hope this advice will empower you in your ganache-making skills. Let us know how you did with it!</p>\n\n"\
|
147
|
+
"<h2>Ganache at <em>Les Bonnes Choses</em></h2>\n\n"\
|
148
|
+
"<p>We have a saying at Les Bonnes Choses: "Once you can make ganache, you can make anything."</p>\n\n"\
|
149
|
+
"<p>As you may know, we like to give our workshop artists the ability to master their art to the top; that is why our Preparation Experts always start off as being Ganache Specialists for Les Bonnes Choses. That way, they're given an opportunity to focus on one exercise before moving on. "\
|
150
|
+
"Once they master their ganache, and are able to provide the most optimal delight to our customers, we consider they'll thrive as they work on other kinds of preparations.</p>\n\n"\
|
151
|
+
"<h2>About the chocolate in our ganache</h2>\n\n"\
|
152
|
+
"<p>Now, we've also had a lot of questions about how our chocolate gets made. It's true, as you might know, that we make it ourselves, from Columbian cocoa and French cow milk, with a process that much resembles the one in the following Discovery Channel documentary.</p>\n\n "\
|
153
|
+
"<div data-oembed=\"http://www.youtube.com/\"\n data-oembed-type=\"video\"\n data-oembed-provider=\"youtube\"><iframe width=\"459\" height=\"344\" src=\"http://www.youtube.com/embed/Ye78F3-CuXY?feature=oembed\" frameborder=\"0\" allowfullscreen></iframe></div>\n"
|
154
|
+
end
|
155
|
+
it "returns a correct as_html on a StructuredText with custom HTML serializer" do
|
156
|
+
@api.form("everything")
|
157
|
+
.query(%([[:d = at(document.id, "#{@api.bookmark('about')}")]]))
|
158
|
+
.submit(@master_ref)[0]['article.content'].as_html(@link_resolver, @html_serializer).gsub("'", "'").should ==
|
159
|
+
"<h2>A tale of pastry and passion</h2>\n\n"\
|
160
|
+
"<p>As a child, Jean-Michel Pastranova learned the art of fine cuisine from his grand-father, Jacques Pastranova, who was the creator of the "taste-design" art current, and still today an unmissable reference of forward-thinking in cuisine. At first an assistant in his grand-father's kitchen, Jean-Michel soon found himself fascinated by sweet flavors and the tougher art of pastry, drawing his own path in the ever-changing cuisine world.</p>\n\n"\
|
161
|
+
"<p>In 1992, the first Les Bonnes Choses store opened on rue Saint-Lazare, in Paris (<a href=\"http://localhost/UlfoxUnM0wkXYXbb\">we're still there!</a>), much to everyone's surprise; indeed, back then, it was very surprising for a highly promising young man with a preordained career as a restaurant chef, to open a pastry shop instead. But soon enough, contemporary chefs understood that Jean-Michel had the drive to redefine a new nobility to pastry, the same way many other kinds of cuisine were being qualified as "fine".</p>\n\n"\
|
162
|
+
"<p>In 1996, meeting an overwhelming demand, Jean-Michel Pastranova opened <a href=\"http://localhost/UlfoxUnM0wkXYXbP\">a second shop on Paris's Champs-Élysées</a>, and <a href=\"http://localhost/UlfoxUnM0wkXYXbr\">a third one in London</a>, the same week! Eventually, Les Bonnes Choses gained an international reputation as "a perfection so familiar and new at the same time, that it will feel like a taste travel" (New York Gazette), "the finest balance between surprise and comfort, enveloped in sweetness" (The Tokyo Tribune), "a renewal of the pastry genre (...), the kind that changed the way pastry is approached globally" (The San Francisco Gourmet News). Therefore, it was only a matter of time before Les Bonnes Choses opened shops in <a href=\"http://localhost/UlfoxUnM0wkXYXbc\">New York</a> (2000) and <a href=\"http://localhost/UlfoxUnM0wkXYXbU\">Tokyo</a> (2004).</p>\n\n"\
|
163
|
+
"<p>In 2013, Jean-Michel Pastranova stepped down as the CEO and Director of Workshops, remaining a senior advisor to the board and to the workshop artists; he passed the light on to Selena, his daugther, who initially learned the art of pastry from him. Passion for great food runs in the Pastranova family...</p>\n\n<img src=\"https://prismic-io.s3.amazonaws.com/lesbonneschoses/df6c1d87258a5bfadf3479b163fd85c829a5c0b8.jpg\" alt=\"\" width=\"800\" height=\"533\" />\n\n"\
|
164
|
+
"<h2>Our main value: our customers' delight</h2>\n\n"\
|
165
|
+
"<p>Our every action is driven by the firm belief that there is art in pastry, and that this art is one of the dearest pleasures one can experience.</p>\n\n"\
|
166
|
+
"<p>At Les Bonnes Choses, people preparing your macarons are not simply "pastry chefs": they are "<a href=\"http://localhost/UlfoxUnM0wkXYXba\">ganache specialists</a>", "<a href=\"http://localhost/UlfoxUnM0wkXYXbQ\">fruit experts</a>", or "<a href=\"http://localhost/UlfoxUnM0wkXYXbn\">oven instrumentalists</a>". They are the best people out there to perform the tasks they perform to create your pastry, giving it the greatest value. And they just love to make their specialized pastry skill better and better until perfection.</p>\n\n"\
|
167
|
+
"<p>Of course, there is a workshop in each <em>Les Bonnes Choses</em> store, and every pastry you buy was made today, by the best pastry specialists in your country.</p>\n\n"\
|
168
|
+
"<p>However, the very difficult art of creating new concepts, juggling with tastes and creating brand new, powerful experiences, is performed every few months, during our "<a href=\"http://localhost/UlfoxUnM0wkXYXbl\">Pastry Art Brainstorms</a>". During the event, the best pastry artists in the world (some working for <em>Les Bonnes Choses</em>, some not) gather in Paris, and showcase the experiments they've been working on; then, the other present artists comment on the piece, and iterate on it together, in order to make it the best possible masterchief!</p>\n\n"\
|
169
|
+
"<p>The session is presided by Jean-Michel Pastranova, who then selects the most delightful experiences, to add it to <em>Les Bonnes Choses</em>'s catalogue.</p>"
|
130
170
|
end
|
131
171
|
it "returns a correct as_html on a StructuredText with links" do
|
132
172
|
@api.form("everything")
|
133
173
|
.query(%([[:d = at(document.id, "#{@api.bookmark('about')}")]]))
|
134
|
-
.submit(@master_ref)[0]['article.content'].as_html(@link_resolver).gsub("'", "'").should ==
|
174
|
+
.submit(@master_ref)[0]['article.content'].as_html(@link_resolver).gsub("'", "'").should ==
|
175
|
+
"<h2>A tale of pastry and passion</h2>\n\n"\
|
176
|
+
"<p>As a child, Jean-Michel Pastranova learned the art of fine cuisine from his grand-father, Jacques Pastranova, who was the creator of the "taste-design" art current, and still today an unmissable reference of forward-thinking in cuisine. At first an assistant in his grand-father's kitchen, Jean-Michel soon found himself fascinated by sweet flavors and the tougher art of pastry, drawing his own path in the ever-changing cuisine world.</p>\n\n"\
|
177
|
+
"<p>In 1992, the first Les Bonnes Choses store opened on rue Saint-Lazare, in Paris (<a href=\"http://localhost/UlfoxUnM0wkXYXbb\">we're still there!</a>), much to everyone's surprise; indeed, back then, it was very surprising for a highly promising young man with a preordained career as a restaurant chef, to open a pastry shop instead. But soon enough, contemporary chefs understood that Jean-Michel had the drive to redefine a new nobility to pastry, the same way many other kinds of cuisine were being qualified as "fine".</p>\n\n"\
|
178
|
+
"<p>In 1996, meeting an overwhelming demand, Jean-Michel Pastranova opened <a href=\"http://localhost/UlfoxUnM0wkXYXbP\">a second shop on Paris's Champs-Élysées</a>, and <a href=\"http://localhost/UlfoxUnM0wkXYXbr\">a third one in London</a>, the same week! Eventually, Les Bonnes Choses gained an international reputation as "a perfection so familiar and new at the same time, that it will feel like a taste travel" (New York Gazette), "the finest balance between surprise and comfort, enveloped in sweetness" (The Tokyo Tribune), "a renewal of the pastry genre (...), the kind that changed the way pastry is approached globally" (The San Francisco Gourmet News). Therefore, it was only a matter of time before Les Bonnes Choses opened shops in <a href=\"http://localhost/UlfoxUnM0wkXYXbc\">New York</a> (2000) and <a href=\"http://localhost/UlfoxUnM0wkXYXbU\">Tokyo</a> (2004).</p>\n\n"\
|
179
|
+
"<p>In 2013, Jean-Michel Pastranova stepped down as the CEO and Director of Workshops, remaining a senior advisor to the board and to the workshop artists; he passed the light on to Selena, his daugther, who initially learned the art of pastry from him. Passion for great food runs in the Pastranova family...</p>\n\n<p class=\"block-img\"><img src=\"https://prismic-io.s3.amazonaws.com/lesbonneschoses/df6c1d87258a5bfadf3479b163fd85c829a5c0b8.jpg\" alt=\"\" width=\"800\" height=\"533\" /></p>\n\n"\
|
180
|
+
"<h2>Our main value: our customers' delight</h2>\n\n"\
|
181
|
+
"<p>Our every action is driven by the firm belief that there is art in pastry, and that this art is one of the dearest pleasures one can experience.</p>\n\n"\
|
182
|
+
"<p>At Les Bonnes Choses, people preparing your macarons are not simply "pastry chefs": they are "<a href=\"http://localhost/UlfoxUnM0wkXYXba\">ganache specialists</a>", "<a href=\"http://localhost/UlfoxUnM0wkXYXbQ\">fruit experts</a>", or "<a href=\"http://localhost/UlfoxUnM0wkXYXbn\">oven instrumentalists</a>". They are the best people out there to perform the tasks they perform to create your pastry, giving it the greatest value. And they just love to make their specialized pastry skill better and better until perfection.</p>\n\n"\
|
183
|
+
"<p>Of course, there is a workshop in each <em>Les Bonnes Choses</em> store, and every pastry you buy was made today, by the best pastry specialists in your country.</p>\n\n"\
|
184
|
+
"<p>However, the very difficult art of creating new concepts, juggling with tastes and creating brand new, powerful experiences, is performed every few months, during our "<a href=\"http://localhost/UlfoxUnM0wkXYXbl\">Pastry Art Brainstorms</a>". During the event, the best pastry artists in the world (some working for <em>Les Bonnes Choses</em>, some not) gather in Paris, and showcase the experiments they've been working on; then, the other present artists comment on the piece, and iterate on it together, in order to make it the best possible masterchief!</p>\n\n"\
|
185
|
+
"<p>The session is presided by Jean-Michel Pastranova, who then selects the most delightful experiences, to add it to <em>Les Bonnes Choses</em>'s catalogue.</p>"
|
135
186
|
end
|
136
187
|
it "returns a correct as_text on a StructuredText" do
|
137
188
|
@api.form("everything")
|
data/spec/prismic_spec.rb
CHANGED
@@ -521,7 +521,8 @@ describe 'SearchForm' do
|
|
521
521
|
"license":"All Rights Reserved"
|
522
522
|
}
|
523
523
|
DATA
|
524
|
-
|
524
|
+
rx = Regexp.escape(data).sub(/"version":"[^"]+"/, '"version":"[^"]+"')
|
525
|
+
@api.form("everything").page_size('1').submit_raw(@master_ref).should =~ /#{rx}/
|
525
526
|
end
|
526
527
|
end
|
527
528
|
end
|
@@ -1,30 +1,31 @@
|
|
1
1
|
{
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
2
|
+
"type": "StructuredText",
|
3
|
+
"value": [{
|
4
|
+
"type": "paragraph",
|
5
|
+
"label": "vanilla",
|
6
|
+
"text": "Experience the ultimate vanilla experience. Our vanilla Macarons are made with our very own (in-house) pure extract of Madagascar vanilla, and subtly dusted with our own vanilla sugar (which we make from real vanilla beans).",
|
7
|
+
"spans": [
|
8
|
+
{
|
9
|
+
"start": 103,
|
10
|
+
"end": 137,
|
11
|
+
"type": "em"
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"start": 11,
|
15
|
+
"end": 14,
|
16
|
+
"type": "hyperlink",
|
17
|
+
"data": {
|
18
|
+
"type": "Link.web",
|
19
|
+
"value": {
|
20
|
+
"url": "http://prismic.io"
|
21
|
+
}
|
22
|
+
}
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"start": 162,
|
26
|
+
"end": 183,
|
27
|
+
"type": "strong"
|
28
|
+
}
|
29
|
+
]
|
30
|
+
}]
|
30
31
|
}
|
@@ -0,0 +1,156 @@
|
|
1
|
+
{
|
2
|
+
"type":"StructuredText",
|
3
|
+
"value":[
|
4
|
+
{
|
5
|
+
"type":"heading1",
|
6
|
+
"text":"Tips to dress a pastry",
|
7
|
+
"spans":[]
|
8
|
+
},
|
9
|
+
{
|
10
|
+
"type":"image",
|
11
|
+
"url":"https://prismic-io.s3.amazonaws.com/lesbonneschoses-vcerzcwaaohojzo/381f3a78dfe952b229fb49ceaa9926f7009ae20a.jpg",
|
12
|
+
"alt":"",
|
13
|
+
"copyright":"",
|
14
|
+
"dimensions":{
|
15
|
+
"width":640,
|
16
|
+
"height":666
|
17
|
+
}
|
18
|
+
},
|
19
|
+
{
|
20
|
+
"type":"paragraph",
|
21
|
+
"text":"Our Pastry Dressers (yes, it is a full-time job in Les Bonnes Choses!) have it somewhat different from our other pastry artists: while the others keep their main focus on the taste, smell, and potentially touch of your pastries, the Pastry Dressers are mainly focused on their looks.",
|
22
|
+
"spans":[
|
23
|
+
{
|
24
|
+
"start":32,
|
25
|
+
"end":47,
|
26
|
+
"type":"hyperlink",
|
27
|
+
"data":{
|
28
|
+
"type":"Link.document",
|
29
|
+
"value":{
|
30
|
+
"document":{
|
31
|
+
"id":"UlfoxUnM0wkXYXbh",
|
32
|
+
"type":"job-offer",
|
33
|
+
"tags":[],
|
34
|
+
"slug":"pastry-dresser"
|
35
|
+
},
|
36
|
+
"isBroken":false
|
37
|
+
}
|
38
|
+
}
|
39
|
+
},
|
40
|
+
{
|
41
|
+
"start":51,
|
42
|
+
"end":68,
|
43
|
+
"type":"em"
|
44
|
+
}
|
45
|
+
]
|
46
|
+
},
|
47
|
+
{
|
48
|
+
"type":"paragraph",
|
49
|
+
"text":"It sometimes makes them feem like they're doing a job that is reasonably different from plain old pastry, and to make the most of your pastry dressings, perhaps so should you!",
|
50
|
+
"spans":[]
|
51
|
+
},
|
52
|
+
{
|
53
|
+
"type":"heading2",
|
54
|
+
"text":"Step by step",
|
55
|
+
"spans":[]
|
56
|
+
},
|
57
|
+
{
|
58
|
+
"type":"paragraph",
|
59
|
+
"text":"From bottom to top, the steps towards a great dressing are pretty clear, and change rarely.",
|
60
|
+
"spans":[]
|
61
|
+
},
|
62
|
+
{
|
63
|
+
"type":"heading3",
|
64
|
+
"text":"Pastry Dresser, or speleologist?",
|
65
|
+
"spans":[]
|
66
|
+
},
|
67
|
+
{
|
68
|
+
"type":"paragraph",
|
69
|
+
"text":"One of the first handy phases of dressing your pastry will be about carving to get to a desired shape and size to build upon. This is very precise work, as you will need to clean the object without breaking it, to remove pieces of it while keeping intact the meaningful bits. Now you're ready to iterate upon it!",
|
70
|
+
"spans":[
|
71
|
+
{
|
72
|
+
"start":173,
|
73
|
+
"end":178,
|
74
|
+
"type":"label",
|
75
|
+
"data":{
|
76
|
+
"label":"author"
|
77
|
+
}
|
78
|
+
}
|
79
|
+
]
|
80
|
+
},
|
81
|
+
{
|
82
|
+
"type":"heading3",
|
83
|
+
"text":"Pastry Dresser, or clay sculptor?",
|
84
|
+
"spans":[]
|
85
|
+
},
|
86
|
+
{
|
87
|
+
"type":"paragraph",
|
88
|
+
"text":"Then, you will need to shape your piece of art into the design you have in mind, by adding the right materials to just the right places. Ganache is your friend in such moments, such as any shape-free material. You'll have to master them, so they obey to the shapes you have in mind.",
|
89
|
+
"spans":[
|
90
|
+
{
|
91
|
+
"start":47,
|
92
|
+
"end":51,
|
93
|
+
"type":"label",
|
94
|
+
"data":{
|
95
|
+
"label":"author"
|
96
|
+
}
|
97
|
+
},
|
98
|
+
{
|
99
|
+
"start":47,
|
100
|
+
"end":51,
|
101
|
+
"type":"strong"
|
102
|
+
}
|
103
|
+
]
|
104
|
+
},
|
105
|
+
{
|
106
|
+
"type":"heading3",
|
107
|
+
"text":"Pastry Dresser, or hairdresser?",
|
108
|
+
"spans":[]
|
109
|
+
},
|
110
|
+
{
|
111
|
+
"type":"paragraph",
|
112
|
+
"text":"The top of the pastry is a priority zone for finalization. This is where your \"last touch\" goes, and it's tremendously important, as it gives the pastry most of its character. You will have to play with the details, to keep the top of your piece on the... top of your priorities!",
|
113
|
+
"spans":[]
|
114
|
+
},
|
115
|
+
{
|
116
|
+
"type":"heading2",
|
117
|
+
"text":"Before starting",
|
118
|
+
"spans":[]
|
119
|
+
},
|
120
|
+
{
|
121
|
+
"type":"paragraph",
|
122
|
+
"text":"Finishing by the beginning: what did we have to consider, before running towards the aforementioned steps?",
|
123
|
+
"spans":[]
|
124
|
+
},
|
125
|
+
{
|
126
|
+
"type":"image",
|
127
|
+
"url":"https://prismic-io.s3.amazonaws.com/lesbonneschoses-vcerzcwaaohojzo/502ebb427b5eb45693800816fc778316c04935f5.jpg",
|
128
|
+
"alt":"",
|
129
|
+
"copyright":"",
|
130
|
+
"dimensions":{
|
131
|
+
"width":640,
|
132
|
+
"height":427
|
133
|
+
}
|
134
|
+
},
|
135
|
+
{
|
136
|
+
"type":"heading3",
|
137
|
+
"text":"Pastry Dresser, or illustrator?",
|
138
|
+
"spans":[]
|
139
|
+
},
|
140
|
+
{
|
141
|
+
"type":"paragraph",
|
142
|
+
"text":"We didn't mention color, but it's a very important component of the piece. Just like an illustrator will pick colors that add to the shape in a matching way to keep a perfect meaning, the colors must be perfect to be consistent with the taste of the piece (do not use green-colored sugar for a strawberry-flavored pastry, if you don't want to gross people out!)",
|
143
|
+
"spans":[]
|
144
|
+
},
|
145
|
+
{
|
146
|
+
"type":"heading3",
|
147
|
+
"text":"Pastry Dresser, or designer?",
|
148
|
+
"spans":[]
|
149
|
+
},
|
150
|
+
{
|
151
|
+
"type":"paragraph",
|
152
|
+
"text":"And even before the illustration and colors, you really need to take the time to think about your destination, to make sure it's nothing short of perfect. This may imply taking the time to sit down for a few minutes with a paper and a pen. The first skill of an imaginative Pastry Dresser is a drawing skill, just like a fashion stylist.",
|
153
|
+
"spans":[]
|
154
|
+
}
|
155
|
+
]
|
156
|
+
}
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,71 +1,72 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prismic.io
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Étienne Vallette d'Osia
|
8
|
+
- Erwan Loisant
|
8
9
|
- Samy Dindane
|
9
10
|
- Rudy Rigot
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date: 2014-09-
|
14
|
+
date: 2014-09-23 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: bundler
|
17
18
|
requirement: !ruby/object:Gem::Requirement
|
18
19
|
requirements:
|
19
|
-
- -
|
20
|
+
- - ~>
|
20
21
|
- !ruby/object:Gem::Version
|
21
22
|
version: '1.3'
|
22
23
|
type: :development
|
23
24
|
prerelease: false
|
24
25
|
version_requirements: !ruby/object:Gem::Requirement
|
25
26
|
requirements:
|
26
|
-
- -
|
27
|
+
- - ~>
|
27
28
|
- !ruby/object:Gem::Version
|
28
29
|
version: '1.3'
|
29
30
|
- !ruby/object:Gem::Dependency
|
30
31
|
name: rspec
|
31
32
|
requirement: !ruby/object:Gem::Requirement
|
32
33
|
requirements:
|
33
|
-
- -
|
34
|
+
- - ~>
|
34
35
|
- !ruby/object:Gem::Version
|
35
36
|
version: '2.14'
|
36
37
|
type: :development
|
37
38
|
prerelease: false
|
38
39
|
version_requirements: !ruby/object:Gem::Requirement
|
39
40
|
requirements:
|
40
|
-
- -
|
41
|
+
- - ~>
|
41
42
|
- !ruby/object:Gem::Version
|
42
43
|
version: '2.14'
|
43
44
|
- !ruby/object:Gem::Dependency
|
44
45
|
name: nokogiri
|
45
46
|
requirement: !ruby/object:Gem::Requirement
|
46
47
|
requirements:
|
47
|
-
- -
|
48
|
+
- - ~>
|
48
49
|
- !ruby/object:Gem::Version
|
49
50
|
version: '1.6'
|
50
51
|
type: :development
|
51
52
|
prerelease: false
|
52
53
|
version_requirements: !ruby/object:Gem::Requirement
|
53
54
|
requirements:
|
54
|
-
- -
|
55
|
+
- - ~>
|
55
56
|
- !ruby/object:Gem::Version
|
56
57
|
version: '1.6'
|
57
58
|
- !ruby/object:Gem::Dependency
|
58
59
|
name: simplecov
|
59
60
|
requirement: !ruby/object:Gem::Requirement
|
60
61
|
requirements:
|
61
|
-
- -
|
62
|
+
- - ~>
|
62
63
|
- !ruby/object:Gem::Version
|
63
64
|
version: '0.7'
|
64
65
|
type: :development
|
65
66
|
prerelease: false
|
66
67
|
version_requirements: !ruby/object:Gem::Requirement
|
67
68
|
requirements:
|
68
|
-
- -
|
69
|
+
- - ~>
|
69
70
|
- !ruby/object:Gem::Version
|
70
71
|
version: '0.7'
|
71
72
|
description: The standard Prismic.io's API library.
|
@@ -75,9 +76,10 @@ executables: []
|
|
75
76
|
extensions: []
|
76
77
|
extra_rdoc_files: []
|
77
78
|
files:
|
78
|
-
-
|
79
|
-
-
|
80
|
-
-
|
79
|
+
- .gitignore
|
80
|
+
- .travis.yml
|
81
|
+
- .yardopts
|
82
|
+
- Changelog.md
|
81
83
|
- Gemfile
|
82
84
|
- Gemfile.lock
|
83
85
|
- README.md
|
@@ -119,6 +121,7 @@ files:
|
|
119
121
|
- spec/responses_mocks/structured_text_heading.json
|
120
122
|
- spec/responses_mocks/structured_text_linkfile.json
|
121
123
|
- spec/responses_mocks/structured_text_paragraph.json
|
124
|
+
- spec/responses_mocks/structured_text_with_labels.json
|
122
125
|
- spec/responses_mocks/structured_text_with_tricky_spans.json
|
123
126
|
- spec/spec_helper.rb
|
124
127
|
homepage: http://prismic.io
|
@@ -131,14 +134,14 @@ require_paths:
|
|
131
134
|
- lib
|
132
135
|
required_ruby_version: !ruby/object:Gem::Requirement
|
133
136
|
requirements:
|
134
|
-
- -
|
137
|
+
- - '>='
|
135
138
|
- !ruby/object:Gem::Version
|
136
139
|
version: '0'
|
137
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
141
|
requirements:
|
139
|
-
- -
|
142
|
+
- - '>='
|
140
143
|
- !ruby/object:Gem::Version
|
141
|
-
version:
|
144
|
+
version: '0'
|
142
145
|
requirements: []
|
143
146
|
rubyforge_project:
|
144
147
|
rubygems_version: 2.2.2
|
@@ -160,5 +163,6 @@ test_files:
|
|
160
163
|
- spec/responses_mocks/structured_text_heading.json
|
161
164
|
- spec/responses_mocks/structured_text_linkfile.json
|
162
165
|
- spec/responses_mocks/structured_text_paragraph.json
|
166
|
+
- spec/responses_mocks/structured_text_with_labels.json
|
163
167
|
- spec/responses_mocks/structured_text_with_tricky_spans.json
|
164
168
|
- spec/spec_helper.rb
|