Metadata-Version: 2.1
Name: wagtail-webstories
Version: 0.0.2
Summary: AMP web story support for Wagtail
Home-page: https://github.com/torchbox/wagtail-webstories/
Author: Matt Westcott
Author-email: matthew@torchbox.com
License: BSD
Description: # wagtail-webstories
        
        AMP web story support for Wagtail
        
        ## Installation
        
        Install with pip:
        
        ```bash
        pip install wagtail-webstories
        ```
        
        Add to INSTALLED_APPS:
        
        ```python
        INSTALLED_APPS = [
            # ...
            'wagtail_webstories',
            # ...
        ]
        ```
        
        Define a model that extends `wagtail_webstories.models.BaseWebStoryPage`:
        
        ```python
        from wagtail_webstories.models import BaseWebStoryPage
        
        class StoryPage(BaseWebStoryPage):
            pass
        ```
        
        Create a corresponding template that extends `wagtail_webstories/base_web_story_page.html`:
        
        ```html+django
        {% extends "wagtail_webstories/base_web_story_page.html" %}
        ```
        
        ## Importing
        
        To enable importing of web stories, define a setting `WAGTAIL_WEBSTORIES_IMPORT_MODEL` pointing to the page model to use:
        
        ```python
        WAGTAIL_WEBSTORIES_IMPORT_MODEL = 'myapp.StoryPage'
        ```
        
        ## HTML cleaning
        
        By default, all HTML elements and attributes not permitted by the AMP web story specification will be stripped out on importing and saving. To disable this, set `WAGTAIL_WEBSTORIES_CLEAN_HTML` to False:
        
        ```python
        WAGTAIL_WEBSTORIES_CLEAN_HTML = False
        ```
        
        
        ## Image importing
        
        By default, image references within imported stories are left at their original URLs. BaseWebStoryPage provides a method `import_images()` to fetch all referenced images and import them into the Wagtail image library, de-duplicating if they already exist. It is recommended that you call this from a `post_save` signal handler:
        
        ```python
        # myapp/signals.py
        
        from django.db.models.signals import post_save
        from django.dispatch import receiver
        
        from .models import StoryPage
        
        
        @receiver(post_save, sender=StoryPage)
        def import_story_images(sender, instance, **kwargs):
            changed = instance.import_images()
            if changed:
                instance.save()
        
        
        # myapp/apps.py
        
        from django.apps import AppConfig
        
        
        class MyappConfig(AppConfig):
            name = 'myapp'
        
            def ready(self):
                import myapp.signals  # noqa
        
        
        # myapp/__init__.py
        
        default_app_config = 'myapp.apps.MyappConfig'
        ```
        
        Since importing images can be a time-consuming process, you may wish to offload the call to `import_images` to a background task using Celery or similar, to avoid this blocking a web server thread.
        
        To customise the creation of new images (e.g. to assign imported images to a particular collection, or to populate additional metadata fields on a custom image model), override the story page model's `_create_image` method:
        
        ```python
        class StoryPage(BaseWebStoryPage):
        
            def _create_image(self, file, title=None):
                image = super()._create_image(file, title=title)
                image.copyright = "All rights reserved"
                return image
        ```
        
        ## Video importing
        
        If you have [wagtailmedia](https://pypi.org/project/wagtailmedia/) installed, you can similarly import videos into the local media library by calling `import_videos()`. The signal handler above then becomes:
        
        ```python
        # myapp/signals.py
        
        @receiver(post_save, sender=StoryPage)
        def import_story_images(sender, instance, **kwargs):
            images_changed = instance.import_images()
            videos_changed = instance.import_videos()
            if images_changed or videos_changed:
                instance.save()
        ```
        
        ## Linking and embedding
        
        To embed a web story into a regular (non-AMP) StreamField-based page, include the `wagtail_webstories.blocks.StoryEmbedBlock` block type in your StreamField definition:
        
        ```python
        from wagtail_webstories.blocks import StoryEmbedBlock
        
        class BlogPage(Page):
            body = StreamField([
                ('heading', blocks.CharBlock()),
                ('paragraph', blocks.RichTextBlock()),
                ('story_embed', StoryEmbedBlock(target_model=StoryPage)),
            ])
        ```
        
        The `target_model` argument is optional - by default, any page type inheriting from BaseWebStoryPage can be chosen. The block will render on the front-end template (when using `{% include_block %}`) as an `<amp-story-player>` element; your template should include [the necessary scripts for rendering this](https://amp.dev/documentation/guides-and-tutorials/integrate/embed-stories/?format=stories#embed-amp-story-player), along with a CSS rule to specify appropriate dimensions:
        
        ```html
            <script async src="https://cdn.ampproject.org/amp-story-player-v0.js"></script>
            <link href="https://cdn.ampproject.org/amp-story-player-v0.css" rel="stylesheet" type="text/css">
            <style>
                amp-story-player { width: 360px; height: 600px; }
            </style>
        ```
        
        To include a link to a story rather than embedding it, `wagtail_webstories.blocks.StoryChooserBlock` can be used in place of `StoryEmbedBlock`. The default template `wagtail_webstories/blocks/story_poster_link.html` outputs a 'card' rendering of the story using the story's poster image, to be used with the following CSS:
        
        ```css
            .webstory-poster {
                display: block; width: 300px; height: 400px; border-radius: 15px; background-size: cover; position: relative;
            }
            .webstory-poster .webstory-info {
                position: absolute; bottom: 0; width: 100%; background-color: #ccc; color: black; border-bottom-left-radius: 15px; border-bottom-right-radius: 15px;
            }
            .webstory-poster .title {
                font-size: 1.5em; padding: 10px;
            }
            .webstory-poster .publisher {
                padding: 0 10px 20px 10px;
            }
            .webstory-poster .publisher img {
                vertical-align: middle;
            }
        ```
        
        The templates `wagtail_webstories/blocks/story_poster_link.html` and `wagtail_webstories/blocks/story_embed_block.html` expect a single variable `page` containing the story page instance, so these can also be used outside of StreamField:
        
        ```python
        # models.py
        class StoryIndexPage(Page):
            def get_context(self, request):
                context = super().get_context(request)
                context['stories'] = StoryPage.objects.child_of(self).live().order_by('-first_published_at')
                return context
        ```
        
        ```html+django
        {# story_index_page.html #}
        {% for story in stories %}
            {% include "wagtail_webstories/blocks/story_poster_link.html" with page=story %}
        {% endfor %}
        ```
        
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Framework :: Wagtail :: 2
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.6
Description-Content-Type: text/markdown
Provides-Extra: testing
