Skip to content

Commit

Permalink
Merge pull request #32 from tailsdotcom/master
Browse files Browse the repository at this point in the history
Add support for composite slices
  • Loading branch information
srenault authored Oct 12, 2017
2 parents 888e262 + 16f33ec commit 172b6bb
Show file tree
Hide file tree
Showing 4 changed files with 233 additions and 8 deletions.
87 changes: 82 additions & 5 deletions prismic/fragments.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,24 @@ def as_html(self, link_resolver):
html.append("""<section data-field="%s">""" % key)
html.append(self.fragment_to_html(fragment, link_resolver))
html.append("""</section>""")

return ''.join(html)

def __getitem__(self, name):
return self.fragments[name]

def __iter__(self):
return iter(self.fragments)

def keys(self):
return self.fragments.keys()

def items(self):
return self.fragments.items()

def values(self):
return self.fragments.values()

# Links

class Link(FragmentElement):
Expand Down Expand Up @@ -224,13 +240,21 @@ def __init__(self, value):
def as_html(self, documentlink_resolver, html_serializer=None):
"""Get the DocumentLink as html.
:param documentlink_resolver: A resolver function will be called with :class:`prismic.fragments.Fragment.DocumentLink <prismic.fragments.Fragment.DocumentLink>` object as argument. Resolver function should return a string, the local url to the document.
:param documentlink_resolver: A resolver function will be called with
:class:`prismic.fragments.Fragment.DocumentLink <prismic.fragments.Fragment.DocumentLink>` object as
argument. Resolver function should return a string, the local url to the document.
"""
return """<a href="%(link)s">%(slug)s</a>""" % {"link": self.get_url(documentlink_resolver), "slug": self.slug}
return """<a href="%(link)s">%(slug)s</a>""" % {
"link": self.get_url(documentlink_resolver),
"slug": self.slug
}

def get_url(self, documentlink_resolver=None):
if not hasattr(documentlink_resolver, '__call__'):
raise Exception("documentlink_resolver should be a callable object, but it's: %s" % type(documentlink_resolver))
raise Exception(
"documentlink_resolver should be a callable object, but it's: %s"
% type(documentlink_resolver)
)
return documentlink_resolver(self)

def get_document_id(self):
Expand Down Expand Up @@ -468,6 +492,8 @@ def as_html(self, link_resolver):
html.append(group_doc.as_html(link_resolver))
return "\n".join(html)

def __iter__(self):
return iter(self.value)

class Slice(FragmentElement):

Expand All @@ -486,6 +512,48 @@ def as_html(self, link_resolver):
"body": self.value.as_html(link_resolver)
}

class CompositeSlice(FragmentElement):

def __init__(self, slice_type, slice_label, elt):
self.slice_type = slice_type
self.slice_label = slice_label
self.repeat = []
self.non_repeat = {}

_repeat = elt.get('repeat')
_non_repeat = elt.get('non-repeat')

if any(_repeat):
self.repeat = self.parse_repeat(_repeat)

if _non_repeat:
self.non_repeat = self.parse_non_repeat(_non_repeat)

@staticmethod
def parse_repeat(repeat):
return Fragment.Group(repeat)

@staticmethod
def parse_non_repeat(non_repeat):
return Fragment.Group([non_repeat])

def as_html(self, link_resolver):
classes = ['slice']
if self.slice_label:
classes.append(self.slice_label)

body = ""
if self.non_repeat:
body += self.non_repeat.as_html(link_resolver)

if self.repeat:
body += self.repeat.as_html(link_resolver)

return '<div data-slicetype="%(slice_type)s" class="%(classes)s">%(body)s</div>' % {
"slice_type": self.slice_type,
"classes": ' '.join(classes),
"body": body
}

class SliceZone(FragmentElement):

Expand All @@ -494,15 +562,24 @@ def __init__(self, value):
for elt in value:
slice_type = elt['slice_type']
slice_label = elt.get('slice_label')
fragment = Fragment.from_json(elt['value'])
self.slices.append(Fragment.Slice(slice_type, slice_label, fragment))

# Old style slice
if 'value' in elt:
fragment = Fragment.from_json(elt['value'])
self.slices.append(Fragment.Slice(slice_type, slice_label, fragment))
else:
Fragment.CompositeSlice(slice_type, slice_label, elt)
self.slices.append(Fragment.CompositeSlice(slice_type, slice_label, elt))

def as_html(self, link_resolver):
html = []
for slice in self.slices:
html.append(slice.as_html(link_resolver))
return "\n".join(html)

def __iter__(self):
return iter(self.slices)


class StructuredText(object):

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setup(
name='prismic',
version='1.4.2',
version='1.5.0',
description='Prismic.io development kit',
author='The Prismic.io Team',
author_email='[email protected]',
Expand Down
17 changes: 15 additions & 2 deletions tests/test_prismic.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from prismic.exceptions import InvalidTokenError, AuthorizationNeededError, InvalidURLError
from .test_prismic_fixtures import fixture_api, fixture_search, fixture_groups, \
fixture_structured_lists, fixture_empty_paragraph, fixture_store_geopoint, fixture_image_links, \
fixture_spans_labels, fixture_block_labels, fixture_custom_html, fixture_slices
fixture_spans_labels, fixture_block_labels, fixture_custom_html, fixture_slices, fixture_composite_slices
import time
import json
import logging
Expand Down Expand Up @@ -37,6 +37,7 @@ def setUp(self):
self.fixture_spans_labels = json.loads(fixture_spans_labels)
self.fixture_custom_html = json.loads(fixture_custom_html)
self.fixture_slices = json.loads(fixture_slices)
self.fixture_composite_slices = json.loads(fixture_composite_slices)

self.api = prismic.Api(self.fixture_api, self.token, ShelveCache("prismictest"), None)

Expand Down Expand Up @@ -409,14 +410,25 @@ def test_slicezone(self):
self.maxDiff = 10000
doc = prismic.Document(self.fixture_slices)
slices = doc.get_slice_zone("article.blocks")
slices_html =slices.as_html(PrismicTestCase.link_resolver)
slices_html = slices.as_html(PrismicTestCase.link_resolver)
expected_html = (
"""<div data-slicetype="features" class="slice"><section data-field="illustration"><img src="https://wroomdev.s3.amazonaws.com/toto/db3775edb44f9818c54baa72bbfc8d3d6394b6ef_hsf_evilsquall.jpg" alt="" width="4285" height="709" /></section>"""
"""<section data-field="title"><span class="text">c'est un bloc features</span></section></div>\n"""
"""<div data-slicetype="text" class="slice"><p>C'est un bloc content</p></div>""")
# Comparing len rather than actual strings because json loading is not in a deterministic order for now
self.assertEqual(len(expected_html), len(slices_html))

def test_composite_slices(self):
self.maxDiff = 1000
doc = prismic.Document(self.fixture_composite_slices)
slices = doc.get_slice_zone("test.body")
slices_html = slices.as_html(PrismicTestCase.link_resolver)
expected_html = """<div data-slicetype="slice-a" class="slice"><section data-field="non-repeat-text"><p>Slice A non-repeat text</p></section><section data-field="non-repeat-title"><h1>Slice A non-repeat title</h1></section><section data-field="repeat-text"><p>Repeatable text A</p></section><section data-field="repeat-title"><h1>Repeatable title A</h1></section>
<section data-field="repeat-text"><p>Repeatable text B</p></section><section data-field="repeat-title"><h1>Repeatable title B</h1></section></div>
<div data-slicetype="slice-b" class="slice"><section data-field="image"><img src="https://prismic-io.s3.amazonaws.com/tails/014c1fe46e3ceaf04b7cc925b2ea7e8027dc607a_mobile_header_tp.png" alt="" width="800" height="500" /></section><section data-field="title"><h1>Slice A non-repeat title</h1></section></div>"""
# Comparing len rather than actual strings because json loading is not in a deterministic order for now
self.assertEqual(len(expected_html), len(slices_html))

def test_image_links(self):
self.maxDiff = 10000
text = prismic.fragments.StructuredText(self.fixture_image_links.get('value'))
Expand Down Expand Up @@ -516,6 +528,7 @@ def test_geopoint_near(self):
.query(predicates.near('my.store.coordinates', 40.689757, -74.0451453, 15))
self.assertEqual(f.data['q'], ['[[:d = geopoint.near(my.store.coordinates, 40.689757, -74.0451453, 15)]]'])


class TestCache(unittest.TestCase):

def setUp(self):
Expand Down
135 changes: 135 additions & 0 deletions tests/test_prismic_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -1246,3 +1246,138 @@
}
}
"""

fixture_composite_slices = """
{
"alternate_languages": [],
"data": {
"test": {
"body": {
"type": "SliceZone",
"value": [
{
"non-repeat": {
"non-repeat-text": {
"type": "StructuredText",
"value": [
{
"spans": [],
"text": "Slice A non-repeat text",
"type": "paragraph"
}
]
},
"non-repeat-title": {
"type": "StructuredText",
"value": [
{
"spans": [],
"text": "Slice A non-repeat title",
"type": "heading1"
}
]
}
},
"repeat": [
{
"repeat-text": {
"type": "StructuredText",
"value": [
{
"spans": [],
"text": "Repeatable text A",
"type": "paragraph"
}
]
},
"repeat-title": {
"type": "StructuredText",
"value": [
{
"spans": [],
"text": "Repeatable title A",
"type": "heading1"
}
]
}
},
{
"repeat-text": {
"type": "StructuredText",
"value": [
{
"spans": [],
"text": "Repeatable text B",
"type": "paragraph"
}
]
},
"repeat-title": {
"type": "StructuredText",
"value": [
{
"spans": [],
"text": "Repeatable title B",
"type": "heading1"
}
]
}
}
],
"slice_label": null,
"slice_type": "slice-a",
"type": "Slice"
},
{
"non-repeat": {
"image": {
"type": "Image",
"value": {
"main": {
"alt": null,
"copyright": null,
"dimensions": {
"height": 500,
"width": 800
},
"url": "https://prismic-io.s3.amazonaws.com/tails/014c1fe46e3ceaf04b7cc925b2ea7e8027dc607a_mobile_header_tp.png"
},
"views": {}
}
},
"title": {
"type": "StructuredText",
"value": [
{
"spans": [],
"text": "Slice A non-repeat title",
"type": "heading1"
}
]
}
},
"repeat": [
{}
],
"slice_label": null,
"slice_type": "slice-b",
"type": "Slice"
}
]
}
}
},
"first_publication_date": "2017-10-10T11:30:08+0000",
"href": "http://tails.prismic.io/api/v1/documents/search?ref=WdyvQCsAAOgSj_r0&q=%5B%5B%3Ad+%3D+at%28document.id%2C+%22WdyvPCsAAOMSj_rf%22%29+%5D%5D",
"id": "WdyvPCsAAOMSj_rf",
"lang": "en-gb",
"last_publication_date": "2017-10-10T11:30:08+0000",
"linked_documents": [],
"slugs": [
"slice-a-non-repeat-title"
],
"tags": [],
"type": "test",
"uid": "test"
}
"""

0 comments on commit 172b6bb

Please sign in to comment.