prismic.io 1.0.0.preview.7 → 1.0.0.preview.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9978093a5e4f4f3529a05df62cbead5aa3bbb31c
4
- data.tar.gz: 9f89d25cd5a8affedcc997e4fefe1d62908df492
3
+ metadata.gz: 22c9fa81f67d2c7120d3d0aeaa476257392d324b
4
+ data.tar.gz: ec3215425959d51198428fa75827b3b69ca14d5b
5
5
  SHA512:
6
- metadata.gz: 078f0e8b7fa42fd89fbaa6e8af7a16639a5e707194d1815004f540b39efec152e9c7bba3507065f5991a2cfff1e9cf1127a11b56461a2304ae1eda4f54a73a5b
7
- data.tar.gz: b34a4a54f34c285ee46ca0bd570dd4c7e8f66b6712372eda66b760a02cf484c3156bdf21724ba61873fc0ab8d6c1a5804199b336586edb3567a503e1b892f2c9
6
+ metadata.gz: 608f58c15fab9a73a487f01b69301679e8ffcc54e4dcbae98bdda8c57d6b69191216d48c63ed5b1e208e5a53b13a0ff498101136d0f3db5ce30011bde8f6573e
7
+ data.tar.gz: c41729c800aeac6d103569cbbee76d4679854e9bc55d0f8956645815f5e5f3e81a58b03da82a5406cc2fcaf0311d2aa17a9179f54397350a6e3090c02bd91419
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- prismic.io (1.0.0.preview.7)
4
+ prismic.io (1.0.0.preview.8)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -37,16 +37,15 @@ On our [prismic.io developer's portal](https://developers.prismic.io/), on top o
37
37
 
38
38
  #### Kit documentation
39
39
 
40
- To get a detailed documentation of the Ruby kit's variables and methods, please check out the [prismic.io Ruby kit's documentation](http://prismicio.github.io/ruby-kit/) (click on the "Class list" tab at the top-right)
40
+ To get a detailed documentation of the Ruby kit's variables and methods, please check out the [prismic.io Ruby kit's documentation](http://rubydoc.info/github/prismicio/ruby-kit/master/frames)
41
41
 
42
42
  Need to see what changed, or to upgrade your kit? Check out [this kit's changelog](changelog.md).
43
43
 
44
44
  ##### Ruby kit's specificities
45
45
 
46
46
  This Ruby kit contains some mild differences and syntastic sugar over [the "Kits and helpers" section of our API documentation](https://developers.prismic.io/documentation/UjBe8bGIJ3EKtgBZ/api-documentation#kits-and-helpers) (which you should read first). They are listed here:
47
- * From the api object, getting a form is done through the `create_search_form` method; a basic querying therefore looks like this: `api.create_search_form("everything").ref(@ref).submit()`.
48
- * When calling the API, a faster way to pass the `ref`: directly as a parameter of the `submit` method (no need to use the `ref` method then): `api.create_search_form("everything").submit(@ref)`.
49
- * Accessing type-dependent fields from a `document` is done through the `[]` operator (rather than a `get()` method). Printing the HTML version of a field therefore looks like `document["title_user_friendly"].as_html(link_resolver(@ref)).html_safe`.
47
+ * When calling the API, a faster way to pass the `ref`: directly as a parameter of the `submit` method (no need to use the `ref` method then): `api.form("everything").submit(@ref)`.
48
+ * Accessing type-dependent fields from a `document` is done through the `[]` operator (rather than a `get()` method). Printing the HTML version of a field therefore looks like `document["title_user_friendly"].as_html(link_resolver(@ref))`.
50
49
  * Two of the fields in the `DocumentLink` object (the one used to write your `link_resolver` method, for instance) were renamed to fit Ruby's best practice: `doc.type` is in fact `doc.link_type`, and `doc.isBroken` is in fact `doc.broken?`.
51
50
 
52
51
  #### Use it
data/changelog.md CHANGED
@@ -1,19 +1,27 @@
1
1
  ## Changelog for prismic.io Ruby development kit
2
2
 
3
+ ### prismic.io.1.0.0.preview.8
4
+
5
+ #### New features
6
+ * Support for group fragments.
7
+ * Support for unknown fragments (instead of crashing, ignores the fragment with a warning advising to update the kit).
8
+
9
+ #### Syntactic sugar
10
+ * `Prismic::API#create_search_form` is now `Prismic::API#form` (the former issues a deprecation warning, and will be removed in a later release); the online cross-tech doc was adapted to reflect that possibility.
3
11
 
4
12
  ### prismic.io.1.0.0.preview.7
5
13
 
6
14
  #### Potentially breaking changes
7
- * Boldness in `Prismic::Fragments::StructuredText#as_html` was represented as `<b>` tags, now as `<strong>` tags (262b5da9219cb990773a5b307f270f899b067ee5)
15
+ * Boldness in `Prismic::Fragments::StructuredText#as_html` was represented as `<b>` tags, now as `<strong>` tags.
8
16
 
9
17
  #### New features
10
- * You had to call `Prismic::Link_resolver#link_to` on a `Prismic::Fragments::DocumentLink` object, but sometimes, you actually have the full `Prismic::Document`; you can now call it on both types of objects (b1a53141e1a962762e00bd904a68d6fcd5c3a6bc).
11
- * You had to call `api.master_ref` to get the master ref; now you can call it `api.master`, just like in the other dev kits; both methods do the same thing (a9e11bbb735601734512a8cefca72ed29a6bdc81).
12
- * New method: `Prismic::Fragments::StructuredText#as_text`, renders zero formatting, and ignores images and embeds (d4c8c751a28afef4ef2c2e0d943cf8066ef3c039).
13
- * `Prismic::SearchForm` only had the `query` method to set the `q` parameter of the API call. Now those methods are dynamically created from the RESTful form found in the `/api` document, so it's now possible to use those methods too: `orderings`, `page`, `pageSize`, as well as all the future non-yet-existing ones (fcb4e3a92dbda1b6901a1065dcf0ef4144871fdd)
18
+ * You had to call `Prismic::Link_resolver#link_to` on a `Prismic::Fragments::DocumentLink` object, but sometimes, you actually have the full `Prismic::Document`; you can now call it on both types of objects.
19
+ * You had to call `api.master_ref` to get the master ref; now you can call it `api.master`, just like in the other dev kits; both methods do the same thing.
20
+ * New method: `Prismic::Fragments::StructuredText#as_text`, renders zero formatting, and ignores images and embeds.
21
+ * `Prismic::SearchForm` only had the `query` method to set the `q` parameter of the API call. Now those methods are dynamically created from the RESTful form found in the `/api` document, so it's now possible to use those methods too: `orderings`, `page`, `pageSize`, as well as all the future non-yet-existing ones.
14
22
 
15
23
 
16
24
  ### prismic.io.1.0.0.preview.6
17
25
 
18
26
  #### Potentially breaking changes
19
- * From an image, you had to call the view with its index, like this `image_object[0]`; now they're stored in a Hash, you have to call them with their proper name: `image_object['large']` (e6312b8d4486c8eacb1de7214563d45c61b5653c).
27
+ * From an image, you had to call the view with its index, like this `image_object[0]`; now they're stored in a Hash, you have to call them with their proper name: `image_object['large']`.
data/lib/prismic/api.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
  module Prismic
3
3
  class API
4
+ @@warned_create_search_form = false
4
5
  attr_reader :json, :access_token, :http_client
5
6
  attr_accessor :refs, :bookmarks, :forms, :tags, :types, :oauth
6
7
 
@@ -38,10 +39,6 @@ module Prismic
38
39
  refs[name.downcase]
39
40
  end
40
41
 
41
- def form(name)
42
- forms[name]
43
- end
44
-
45
42
  # Returns a {Prismic::SearchForm search form} by its name
46
43
  # @api
47
44
  # @param name [String] The name of the form
@@ -49,11 +46,20 @@ module Prismic
49
46
  # @param ref [type] Default {Ref reference}
50
47
  #
51
48
  # @return [SearchForm] The search form
52
- def create_search_form(name, data={}, ref={})
53
- form = self.form(name)
49
+ def form(name, data={}, ref={})
50
+ form = self.forms[name]
54
51
  form and form.create_search_form(data, ref)
55
52
  end
56
53
 
54
+ # @deprecated Use {#form} instead.
55
+ def create_search_form(name, data={}, ref={})
56
+ if !@@warned_create_search_form
57
+ warn "[DEPRECATION] `create_search_form` is deprecated. Please use `form` instead."
58
+ @@warned_create_search_form = true
59
+ end
60
+ form(name, data, ref)
61
+ end
62
+
57
63
  def as_json
58
64
  @json
59
65
  end
@@ -0,0 +1,57 @@
1
+ module Prismic
2
+ module Fragments
3
+
4
+ # A fragment of type Group, which contains an array of FragmentList (which itself is a Hash of fragments).
5
+ #
6
+ # For instance, imagining this group is defined with two possible fragments :
7
+ # an image fragment "image", and a text fragment "caption";
8
+ # then accessing the first image will look like this: group[0]['image'].
9
+ class Group < Fragment
10
+
11
+ # The array of the fragment lists
12
+ attr_accessor :fragment_list_array
13
+
14
+ def initialize(fragment_list_array)
15
+ @fragment_list_array = fragment_list_array
16
+ end
17
+
18
+ # Accessing the i-th item (fragment list) of the group: group[i]
19
+ def [](i)
20
+ @fragment_list_array[i]
21
+ end
22
+
23
+ def as_html(link_resolver = nil)
24
+ @fragment_list_array.map { |fl| fl.as_html(link_resolver) }.join("\n")
25
+ end
26
+
27
+ def as_text
28
+ @fragment_list_array.map { |fl| fl.as_text }.join("\n")
29
+ end
30
+
31
+ class FragmentMapping
32
+
33
+ # a hash containing all the fragments in the fragment list
34
+ attr_accessor :fragments
35
+
36
+ def initialize(fragments)
37
+ @fragments = fragments
38
+ end
39
+
40
+ # Accessing the right fragment of the fragment list: fl['caption']
41
+ def [](name)
42
+ @fragments[name]
43
+ end
44
+
45
+ def as_html(link_resolver = nil)
46
+ @fragments.map { |name, fragment|
47
+ %(<section data-field="#{name}">#{fragment.as_html(link_resolver)}</section>)
48
+ }.join("\n")
49
+ end
50
+
51
+ def as_text
52
+ @fragments.values.map { |fragment| fragment.as_text }.join("\n")
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -2,8 +2,17 @@
2
2
  module Prismic
3
3
  module Fragments
4
4
  class Link < Fragment
5
+
6
+ def start_html(link_resolver = nil)
7
+ %(<a href="#@url">)
8
+ end
9
+
10
+ def end_html(link_resolver = nil)
11
+ %(</a>)
12
+ end
13
+
5
14
  def as_html(link_resolver=nil)
6
- %(<a href="#@url">#@url</a>)
15
+ %(#{start_html(link_resolver)}#@url#{end_html(link_resolver)})
7
16
  end
8
17
  end
9
18
 
@@ -34,12 +43,17 @@ module Prismic
34
43
  @broken = broken
35
44
  end
36
45
 
37
- def as_html(link_resolver)
38
- if broken?
39
- %(<span>#{slug}</span>)
40
- else
41
- %(<a href="#{link_resolver.link_to(self)}">#{slug}</a>)
42
- end
46
+ def start_html(link_resolver)
47
+ raise "A link_resolver method is needed to serialize document links into a correct URL on your website. If you're using a starter kit, a trivial one is provided out-of-the-box, that you can update later." if link_resolver == nil
48
+ broken? ? %(<span>) : %(<a href="#{link_resolver.link_to(self)}">)
49
+ end
50
+
51
+ def end_html(link_resolver = nil)
52
+ broken? ? %(</span>) : %(</a>)
53
+ end
54
+
55
+ def as_html(link_resolver=nil)
56
+ %(#{start_html(link_resolver)}#{slug}#{end_html(link_resolver)})
43
57
  end
44
58
 
45
59
  alias :broken? :broken
@@ -2,7 +2,12 @@
2
2
  module Prismic
3
3
  module Fragments
4
4
  class StructuredText < Fragment
5
- class Group
5
+
6
+ # Used during the call of {StructuredText#as_html} : blocks are first gathered by groups,
7
+ # so that list items of the same list are placed within the same group, allowing to frame
8
+ # their serialization with <ul>...</ul> or <ol>...</ol>.
9
+ # Images, paragraphs, headings, embed, ... are then placed alone in their own BlockGroup.
10
+ class BlockGroup
6
11
  attr_reader :kind, :blocks
7
12
  def initialize(kind)
8
13
  @kind = kind
@@ -18,7 +23,16 @@ module Prismic
18
23
  @blocks = blocks
19
24
  end
20
25
 
26
+ # Serializes the current StructuredText fragment into a fully usable HTML code.
27
+ # You need to pass a proper link_resolver so that internal links are turned into the proper URL in
28
+ # your website. If you use a starter kit, one is provided, that you can still update later.
29
+ #
30
+ # This method simply executes the as_html methods on blocks;
31
+ # it is not advised to override this method if you want to change the HTML output, you should
32
+ # override the as_html method at the block level (like {Heading.as_html}, or {Preformatted.as_html},
33
+ # for instance).
21
34
  def as_html(link_resolver)
35
+ # Defining blocks that deserve grouping, assigning them "group kind" names
22
36
  block_group = ->(block){
23
37
  case block
24
38
  when Block::ListItem
@@ -27,13 +41,16 @@ module Prismic
27
41
  nil
28
42
  end
29
43
  }
44
+ # Initializing groups, which is an array of BlockGroup objects
30
45
  groups, last = [], nil
31
46
  blocks.each {|block|
32
47
  group = block_group.(block)
33
- groups << Group.new(group) if !last || group != last
48
+ groups << BlockGroup.new(group) if !last || group != last
34
49
  groups.last << block
35
50
  last = group
36
51
  }
52
+ # HTML-serializing the groups object (delegating the serialization of Block objects),
53
+ # without forgetting to frame the BlockGroup objects right if needed
37
54
  groups.map{|group|
38
55
  html = group.blocks.map{|b| b.as_html(link_resolver) }.join
39
56
  case group.kind
@@ -96,19 +113,18 @@ module Prismic
96
113
  "</strong>"
97
114
  end
98
115
  end
99
-
116
+
100
117
  class Hyperlink < Span
101
118
  attr_accessor :link
102
119
  def initialize(start, finish, link)
103
120
  super(start, finish)
104
121
  @link = link
105
122
  end
106
- def start_html(link_resolver)
107
- # Quick-and-dirty way to generate the right <a> tag
108
- link.as_html(link_resolver).sub(/(<[^>]+>).*/, '\1')
123
+ def start_html(link_resolver = nil)
124
+ link.start_html(link_resolver)
109
125
  end
110
126
  def end_html(link_resolver=nil)
111
- "</a>"
127
+ link.end_html(link_resolver)
112
128
  end
113
129
  end
114
130
  end
@@ -1,9 +1,9 @@
1
1
  # encoding: utf-8
2
2
  require 'prismic/fragments/fragment'
3
- require 'prismic/fragments/block'
4
3
  require 'prismic/fragments/color'
5
4
  require 'prismic/fragments/date'
6
5
  require 'prismic/fragments/embed'
6
+ require 'prismic/fragments/group'
7
7
  require 'prismic/fragments/image'
8
8
  require 'prismic/fragments/link'
9
9
  require 'prismic/fragments/multiple'
@@ -2,6 +2,7 @@
2
2
  module Prismic
3
3
  module JsonParser
4
4
  class << self
5
+ @@warned_unknown_type = []
5
6
  def parsers
6
7
  @parsers ||= {
7
8
  'Link.document' => method(:document_link_parser),
@@ -15,6 +16,7 @@ module Prismic
15
16
  'StructuredText' => method(:structured_text_parser),
16
17
  'Select' => method(:select_parser),
17
18
  'Multiple' => method(:multiple_parser),
19
+ 'Group' => method(:group_parser)
18
20
  }
19
21
  end
20
22
 
@@ -158,8 +160,28 @@ module Prismic
158
160
  Prismic::Fragments::Multiple.new(fragments)
159
161
  end
160
162
 
163
+ def group_parser(json)
164
+ fragment_list_array = []
165
+ json['value'].each do |group|
166
+ fragments = Hash[ group.map {|name, fragment| [name, parsers[fragment['type']].call(fragment)] }]
167
+ fragment_list_array << Prismic::Fragments::Group::FragmentMapping.new(fragments)
168
+ end
169
+ Prismic::Fragments::Group.new(fragment_list_array)
170
+ end
171
+
161
172
  def document_parser(json)
162
173
  data_json = json['data'].values.first # {"doc_type": data}
174
+
175
+ # Removing the unknown types + sending a warning, once
176
+ data_json.select!{ |_, fragment|
177
+ known_type = fragment.is_a?(Array) || parsers.include?(fragment['type'])
178
+ if !known_type && !@@warned_unknown_type.include?(fragment['type'])
179
+ warn "Type #{fragment['type']} is unknown, fragment was skipped; perhaps you should update your prismic.io gem?"
180
+ @@warned_unknown_type << fragment['type']
181
+ end
182
+ known_type
183
+ }
184
+
163
185
  fragments = Hash[data_json.map { |name, fragment|
164
186
  if fragment.is_a? Array
165
187
  [name, multiple_parser(fragment)]
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
  module Prismic
3
3
 
4
- VERSION = "1.0.0.preview.7"
4
+ VERSION = "1.0.0.preview.8"
5
5
 
6
6
  end
data/lib/prismic.rb CHANGED
@@ -62,22 +62,23 @@ module Prismic
62
62
 
63
63
  # A SearchForm represent a Form returned by the prismic.io API.
64
64
  #
65
- # These forms depend on the prismic.io repository, and can be fill and send
66
- # in the same way than regular HTML forms.
65
+ # These forms depend on the prismic.io repository, and can be filled and sent
66
+ # as regular HTML forms.
67
67
  #
68
- # Get SearchForm instance through the {API#create_search_form} method.
68
+ # You may get a SearchForm instance through the {API#form} method.
69
69
  #
70
70
  # The SearchForm instance contains helper methods for each predefined form's fields.
71
- # Note that these methods are not be created if they risk to add confusion:
71
+ # Note that these methods are not created if they risk to add confusion:
72
72
  # - only letters, underscore and digits are authorized in the name
73
73
  # - name starting with a digit or an underscore are forbidden
74
74
  # - generated method can't override existing methods
75
75
  #
76
76
  # @example
77
- # search_form = api.create_search_form('everything')
77
+ # search_form = api.form('everything')
78
78
  # search_form.page(3) # specify the field 'page'
79
79
  # search_form.page_size("20") # specify the 'page_size' field
80
80
  # results = search_form.submit(master_ref) # submit the search form
81
+ # results = api.form('everything').page(3).page_size("20").submit(master_ref) # methods can be chained
81
82
  class SearchForm
82
83
  attr_accessor :api, :form, :data, :ref
83
84
 
@@ -544,6 +544,9 @@ describe 'StructuredText::Hyperlink' do
544
544
  it "can generate valid link" do
545
545
  @hyperlink.start_html(@link_resolver).should == '<a href="http://localhost/UdUjvt_mqVNObPeO">'
546
546
  end
547
+ it "raises an error when no link_resolver provided" do
548
+ expect { @hyperlink.start_html(nil) }.to raise_error
549
+ end
547
550
  it "can generate valid html for broken link" do
548
551
  @link.broken = true
549
552
  @hyperlink.start_html(@link_resolver).should == "<span>"
@@ -565,3 +568,21 @@ describe 'Multiple' do
565
568
  end
566
569
  end
567
570
  end
571
+
572
+ describe 'Group' do
573
+ before do
574
+ @micro_api = Prismic.api("https://micro.prismic.io/api", nil)
575
+ @master_ref = @micro_api.master_ref
576
+ @docchapter = @micro_api.form("everything").query(%([[:d = at(document.type, "docchapter")]])).orderings('[my.docchapter.priority]').submit(@master_ref)[0]
577
+ @link_resolver = Prismic.link_resolver("master"){|doc_link| "http://localhost/#{doc_link.link_type}/#{doc_link.id}" }
578
+ end
579
+
580
+ it 'accesses fields the proper way' do
581
+ @docchapter['docchapter.docs'][0]['linktodoc'].link_type.should == 'doc'
582
+ end
583
+
584
+ it 'serializes towards HTML as expected' do
585
+ @docchapter['docchapter.docs'].as_html(@link_resolver).should == "<section data-field=\"linktodoc\"><a href=\"http://localhost/doc/UrDofwEAALAdpbNH\">with-jquery</a></section>\n<section data-field=\"linktodoc\"><a href=\"http://localhost/doc/UrDp8AEAAPUdpbNL\">with-bootstrap</a></section>"
586
+ end
587
+
588
+ end
@@ -1,4 +1,6 @@
1
1
  # encoding: utf-8
2
+ require 'spec_helper'
3
+
2
4
  describe 'document_link_parser' do
3
5
  before do
4
6
  raw_json = <<json
@@ -326,3 +328,15 @@ json
326
328
  multiple[0].class.should == Prismic::Fragments::Text
327
329
  end
328
330
  end
331
+
332
+ describe 'unknown_parser' do
333
+ before do
334
+ @raw_json = File.read("#{File.dirname(__FILE__)}/responses_mocks/document_with_unknown_fragment.json")
335
+ @json = JSON.parse(@raw_json)
336
+ end
337
+
338
+ it "raises the proper error" do
339
+ Prismic::JsonParser.should_receive(:warn).with("Type blabla is unknown, fragment was skipped; perhaps you should update your prismic.io gem?")
340
+ Prismic::JsonParser.document_parser(@json).fragments.size.should == 2
341
+ end
342
+ end
@@ -15,21 +15,21 @@ describe 'LesBonnesChoses' do
15
15
 
16
16
  describe 'query' do
17
17
  it "queries everything and returns 20 documents" do
18
- @api.create_search_form("everything").submit(@master_ref).size.should == 20
18
+ @api.form("everything").submit(@master_ref).size.should == 20
19
19
  end
20
20
 
21
21
  it "queries macarons (using a predicate) and returns 7 documents" do
22
- @api.create_search_form("everything")
22
+ @api.form("everything")
23
23
  .query(%([[:d = any(document.tags, ["Macaron"])]]))
24
24
  .submit(@master_ref).size.should == 7
25
25
  end
26
26
 
27
27
  it "queries macarons (using a form) and returns 7 documents" do
28
- @api.create_search_form("macarons").submit(@master_ref).size.should == 7
28
+ @api.form("macarons").submit(@master_ref).size.should == 7
29
29
  end
30
30
 
31
31
  it "queries macarons or cupcakes (using a form + a predicate) and returns 11 documents" do
32
- @api.create_search_form("products")
32
+ @api.form("products")
33
33
  .query(%([[:d = any(document.tags, ["Cupcake", "Macaron"])]]))
34
34
  .submit(@master_ref).size.should == 11
35
35
  end
@@ -37,7 +37,7 @@ describe 'LesBonnesChoses' do
37
37
 
38
38
  describe 'API::Document' do
39
39
  before do
40
- @document = @api.create_search_form('everything').query(%([[:d = at(document.id, "UkL0gMuvzYUANCpf")]])).submit(@master_ref)[0]
40
+ @document = @api.form('everything').query(%([[:d = at(document.id, "UkL0gMuvzYUANCpf")]])).submit(@master_ref)[0]
41
41
  end
42
42
 
43
43
  it 'Operator [] works on document' do
@@ -55,17 +55,32 @@ describe 'LesBonnesChoses' do
55
55
  end
56
56
  end
57
57
 
58
- describe 'fragments' do
59
- it "returns a correct as_text on a StructuredText" do
60
- @api.create_search_form("everything")
61
- .query(%([[:d = at(document.id, "UkL0gMuvzYUANCps")]]))
62
- .submit(@master_ref)[0].fragments['body'].as_text.should == "The end of a chapter the beginning of a new one Jean-Michel Pastranova, the founder of Les Bonnes Choses, and creator of the whole concept of modern fine pastry, has decided to step down as the CEO and the Director of Workshops of Les Bonnes Choses, to focus on other projects, among which his now best-selling pastry cook books, but also to take on a primary role in a culinary television show to be announced later this year. \"I believe I've taken the Les Bonnes Choses concept as far as it can go. Les Bonnes Choses is already an entity that is driven by its people, thanks to a strong internal culture, so I don't feel like they need me as much as they used to. I'm sure they are greater ways to come, to innovate in pastry, and I'm sure Les Bonnes Choses's coming innovation will be even more mind-blowing than if I had stayed longer.\" He will remain as a senior advisor to the board, and to the workshop artists, as his daughter Selena, who has been working with him for several years, will fulfill the CEO role from now on. \"My father was able not only to create a revolutionary concept, but also a company culture that puts everyone in charge of driving the company's innovation and quality. That gives us years, maybe decades of revolutionary ideas to come, and there's still a long, wonderful path to walk in the fine pastry world.\""
58
+ describe 'Fragments' do
59
+ before do
60
+ @link_resolver = Prismic.link_resolver("master"){|doc_link| "http://localhost/#{doc_link.id}" }
63
61
  end
62
+ describe 'API::Fragments::StructuredText' do
63
+ it "returns a correct as_html on a StructuredText with list, span, embed and image" do
64
+ @api.form("everything")
65
+ .query(%([[:d = at(document.id, "UkL0gMuvzYUANCpr")]]))
66
+ .submit(@master_ref)[0]['blog-post.body'].as_html(@link_resolver).gsub("&#39;", "'").should == "<h1>Get the right approach to ganache</h1>\n\n<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<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<h2>How to approach ganache</h2>\n\n<img src=\"https://prismic-io.s3.amazonaws.com/lesbonneschoses/ee7b984b98db4516aba2eabd54ab498293913c6c.jpg\" alt=\"\" width=\"640\" height=\"425\" />\n\n<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?). 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<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><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<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<h2>Ganache at <em>Les Bonnes Choses</h2>\n\n<p>We have a saying at Les Bonnes Choses: &quot;Once you can make ganache, you can make anything.&quot;</p>\n\n<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. 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<h2>About the chocolate in our ganache</h2>\n\n<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 <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"
67
+ end
68
+ it "returns a correct as_html on a StructuredText with links" do
69
+ @api.form("everything")
70
+ .query(%([[:d = at(document.id, "#{@api.bookmark('about')}")]]))
71
+ .submit(@master_ref)[0]['article.content'].as_html(@link_resolver).gsub("&#39;", "'").should == "<h2>A tale of pastry and passion</h2>\n\n<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 &quot;taste-design&quot; 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<p>In 1992, the first Les Bonnes Choses store opened on rue Saint-Lazare, in Paris (<a href=\"http://localhost/UkL0gMuvzYUANCpa\">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 &quot;fine&quot;.</p>\n\n<p>In 1996, meeting an overwhelming demand, Jean-Michel Pastranova opened <a href=\"http://localhost/UkL0gMuvzYUANCpX\">a second shop on Paris's Champs-Élysées</a>, and <a href=\"http://localhost/UkL0gMuvzYUANCpY\">a third one in London</a>, the same week! Eventually, Les Bonnes Choses gained an international reputation as &quot;a perfection so familiar and new at the same time, that it will feel like a taste travel&quot; (New York Gazette), &quot;the finest balance between surprise and comfort, enveloped in sweetness&quot; (The Tokyo Tribune), &quot;a renewal of the pastry genre (...), the kind that changed the way pastry is approached globally&quot; (The San Francisco Gourmet News). Therefore, it was only a matter of time before Les Bonnes Choses opened shops in <a href=\"http://localhost/UkL0gMuvzYUANCpW\">New York</a> (2000) and <a href=\"http://localhost/UkL0gMuvzYUANCpZ\">Tokyo</a> (2004).</p>\n\n<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<h2>Our main value: our customers' delight</h2>\n\n<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<p>At Les Bonnes Choses, people preparing your macarons are not simply &quot;pastry chefs&quot;: they are &quot;<a href=\"http://localhost/UkL0gMuvzYUANCpe\">ganache specialists</a>&quot;, &quot;<a href=\"http://localhost/UkL0gMuvzYUANCpc\">fruit experts</a>&quot;, or &quot;<a href=\"http://localhost/UkL0gMuvzYUANCpb\">oven instrumentalists</a>&quot;. 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<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<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 &quot;<a href=\"http://localhost/UkL0gMuvzYUANCpo\">Pastry Art Brainstorms</a>&quot;. 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<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>"
72
+ end
73
+ it "returns a correct as_text on a StructuredText" do
74
+ @api.form("everything")
75
+ .query(%([[:d = at(document.id, "UkL0gMuvzYUANCps")]]))
76
+ .submit(@master_ref)[0]['blog-post.body'].as_text.should == "The end of a chapter the beginning of a new one Jean-Michel Pastranova, the founder of Les Bonnes Choses, and creator of the whole concept of modern fine pastry, has decided to step down as the CEO and the Director of Workshops of Les Bonnes Choses, to focus on other projects, among which his now best-selling pastry cook books, but also to take on a primary role in a culinary television show to be announced later this year. \"I believe I've taken the Les Bonnes Choses concept as far as it can go. Les Bonnes Choses is already an entity that is driven by its people, thanks to a strong internal culture, so I don't feel like they need me as much as they used to. I'm sure they are greater ways to come, to innovate in pastry, and I'm sure Les Bonnes Choses's coming innovation will be even more mind-blowing than if I had stayed longer.\" He will remain as a senior advisor to the board, and to the workshop artists, as his daughter Selena, who has been working with him for several years, will fulfill the CEO role from now on. \"My father was able not only to create a revolutionary concept, but also a company culture that puts everyone in charge of driving the company's innovation and quality. That gives us years, maybe decades of revolutionary ideas to come, and there's still a long, wonderful path to walk in the fine pastry world.\""
77
+ end
64
78
 
65
- it "returns a correct as_text on a StructuredText with a separator" do
66
- @api.create_search_form("everything")
67
- .query(%([[:d = at(document.id, "UkL0gMuvzYUANCps")]]))
68
- .submit(@master_ref)[0].fragments['body'].as_text(' #### ').should == "The end of a chapter the beginning of a new one #### Jean-Michel Pastranova, the founder of Les Bonnes Choses, and creator of the whole concept of modern fine pastry, has decided to step down as the CEO and the Director of Workshops of Les Bonnes Choses, to focus on other projects, among which his now best-selling pastry cook books, but also to take on a primary role in a culinary television show to be announced later this year. #### \"I believe I've taken the Les Bonnes Choses concept as far as it can go. Les Bonnes Choses is already an entity that is driven by its people, thanks to a strong internal culture, so I don't feel like they need me as much as they used to. I'm sure they are greater ways to come, to innovate in pastry, and I'm sure Les Bonnes Choses's coming innovation will be even more mind-blowing than if I had stayed longer.\" #### He will remain as a senior advisor to the board, and to the workshop artists, as his daughter Selena, who has been working with him for several years, will fulfill the CEO role from now on. #### \"My father was able not only to create a revolutionary concept, but also a company culture that puts everyone in charge of driving the company's innovation and quality. That gives us years, maybe decades of revolutionary ideas to come, and there's still a long, wonderful path to walk in the fine pastry world.\""
79
+ it "returns a correct as_text on a StructuredText with a separator" do
80
+ @api.form("everything")
81
+ .query(%([[:d = at(document.id, "UkL0gMuvzYUANCps")]]))
82
+ .submit(@master_ref)[0]['blog-post.body'].as_text(' #### ').should == "The end of a chapter the beginning of a new one #### Jean-Michel Pastranova, the founder of Les Bonnes Choses, and creator of the whole concept of modern fine pastry, has decided to step down as the CEO and the Director of Workshops of Les Bonnes Choses, to focus on other projects, among which his now best-selling pastry cook books, but also to take on a primary role in a culinary television show to be announced later this year. #### \"I believe I've taken the Les Bonnes Choses concept as far as it can go. Les Bonnes Choses is already an entity that is driven by its people, thanks to a strong internal culture, so I don't feel like they need me as much as they used to. I'm sure they are greater ways to come, to innovate in pastry, and I'm sure Les Bonnes Choses's coming innovation will be even more mind-blowing than if I had stayed longer.\" #### He will remain as a senior advisor to the board, and to the workshop artists, as his daughter Selena, who has been working with him for several years, will fulfill the CEO role from now on. #### \"My father was able not only to create a revolutionary concept, but also a company culture that puts everyone in charge of driving the company's innovation and quality. That gives us years, maybe decades of revolutionary ideas to come, and there's still a long, wonderful path to walk in the fine pastry world.\""
83
+ end
69
84
  end
70
85
  end
71
86
  end
data/spec/prismic_spec.rb CHANGED
@@ -58,14 +58,30 @@ describe 'Api' do
58
58
  end
59
59
  end
60
60
 
61
- describe 'form' do
61
+ describe 'forms' do
62
62
  it "return the right Form" do
63
- @api.form('form2').name.should == 'form2'
63
+ @api.forms['form2'].name.should == 'form2'
64
64
  end
65
65
  end
66
66
 
67
67
  describe 'create_search_form' do
68
68
  it "create a new search form for the right form" do
69
+ @form = @api.form('form2')
70
+ @form.form.name.should == 'form2'
71
+ end
72
+ it "store default value as simple value when the field is not repeatable" do
73
+ @form = @api.form('form2')
74
+ @form.data['param1'].should == 'value1'
75
+ end
76
+ it "store default value as array when the field is repeatable" do
77
+ @form = @api.form('form2')
78
+ @form.data['q'].should == ['[[any(document.type, [\"product\"])]]']
79
+ end
80
+ end
81
+
82
+ describe 'deprecated create_search_form' do
83
+ it "create a new search form for the right form" do
84
+ @api.should_receive(:warn).with("[DEPRECATION] `create_search_form` is deprecated. Please use `form` instead.")
69
85
  @form = @api.create_search_form('form2')
70
86
  @form.form.name.should == 'form2'
71
87
  end
@@ -0,0 +1,37 @@
1
+ {
2
+ "id": "UdUkXt_mqZBObPeS",
3
+ "type": "product",
4
+ "href": "doc-url",
5
+ "tags": [
6
+ "Macaron"
7
+ ],
8
+ "slugs": [
9
+ "vanilla-macaron"
10
+ ],
11
+ "data": {
12
+ "product": {
13
+ "name": {
14
+ "type": "StructuredText",
15
+ "value": [
16
+ {
17
+ "type": "heading1",
18
+ "text": "Vanilla Macaron",
19
+ "spans": []
20
+ }
21
+ ]
22
+ },
23
+ "short_lede": {
24
+ "type": "blabla",
25
+ "value": "foo"
26
+ },
27
+ "short_lede2": {
28
+ "type": "blabla",
29
+ "value": "foo"
30
+ },
31
+ "allergens": {
32
+ "type": "Text",
33
+ "value": "Contains almonds, eggs, milk"
34
+ }
35
+ }
36
+ }
37
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prismic.io
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.preview.7
4
+ version: 1.0.0.preview.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Étienne Vallette d'Osia
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-12-16 00:00:00.000000000 Z
12
+ date: 2013-12-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -85,11 +85,11 @@ files:
85
85
  - lib/prismic/api.rb
86
86
  - lib/prismic/form.rb
87
87
  - lib/prismic/fragments.rb
88
- - lib/prismic/fragments/block.rb
89
88
  - lib/prismic/fragments/color.rb
90
89
  - lib/prismic/fragments/date.rb
91
90
  - lib/prismic/fragments/embed.rb
92
91
  - lib/prismic/fragments/fragment.rb
92
+ - lib/prismic/fragments/group.rb
93
93
  - lib/prismic/fragments/image.rb
94
94
  - lib/prismic/fragments/link.rb
95
95
  - lib/prismic/fragments/multiple.rb
@@ -106,6 +106,7 @@ files:
106
106
  - spec/prismic_spec.rb
107
107
  - spec/responses_mocks/api.json
108
108
  - spec/responses_mocks/document.json
109
+ - spec/responses_mocks/document_with_unknown_fragment.json
109
110
  - spec/responses_mocks/fragments.json
110
111
  - spec/responses_mocks/structured_text_heading.json
111
112
  - spec/responses_mocks/structured_text_paragraph.json
@@ -141,7 +142,9 @@ test_files:
141
142
  - spec/prismic_spec.rb
142
143
  - spec/responses_mocks/api.json
143
144
  - spec/responses_mocks/document.json
145
+ - spec/responses_mocks/document_with_unknown_fragment.json
144
146
  - spec/responses_mocks/fragments.json
145
147
  - spec/responses_mocks/structured_text_heading.json
146
148
  - spec/responses_mocks/structured_text_paragraph.json
147
149
  - spec/spec_helper.rb
150
+ has_rdoc:
@@ -1,5 +0,0 @@
1
- # encoding: utf-8
2
- module Prismic
3
- module Fragments
4
- end
5
- end