package Statocles::Document;
$Statocles::Document::VERSION = '0.073';
# ABSTRACT: Base class for all Statocles documents

use Statocles::Base 'Class';
use Statocles::Image;

#pod =attr path
#pod
#pod The path to this document. This is not settable from the frontmatter.
#pod
#pod =cut

has path => (
    is => 'rw',
    isa => Path,
    coerce => Path->coercion,
);

#pod =attr store
#pod
#pod The Store this document comes from. This is not settable from the
#pod frontmatter.
#pod
#pod =cut

has store => (
    is => 'ro',
    isa => Store,
    coerce => Store->coercion,
);

#pod =attr title
#pod
#pod     ---
#pod     title: My First Post
#pod     ---
#pod
#pod The title of this document. Used in the template and the main page
#pod title. Any unsafe characters in the title (C<E<lt>>, C<E<gt>>, C<">, and
#pod C<&>) will be escaped by the template, so no HTML allowed.
#pod
#pod =cut

has title => (
    is => 'rw',
    isa => Str,
);

#pod =attr author
#pod
#pod     ---
#pod     author: preaction <doug@example.com>
#pod     ---
#pod
#pod The author of this document. Optional.
#pod
#pod =cut

has author => (
    is => 'rw',
    isa => Str,
);

#pod =attr status
#pod
#pod The publishing status of this document.  Optional. Statocles apps can
#pod examine this to determine whether to turn a document into a page.  The
#pod default value is C<published>; other reasonable values could include
#pod C<draft> or C<private>.
#pod
#pod =cut

has status => (
    is => 'rw',
    isa => Str,
    default => 'published',
);

#pod =attr content
#pod
#pod The raw content of this document, in markdown. This is everything below
#pod the ending C<---> of the frontmatter.
#pod
#pod =cut

has content => (
    is => 'rw',
    isa => Str,
);

#pod =attr tags
#pod
#pod     ---
#pod     tags: recipe, beef, cheese
#pod     tags:
#pod         - recipe
#pod         - beef
#pod         - cheese
#pod     ---
#pod
#pod The tags for this document. Tags are used to categorize documents.
#pod
#pod Tags may be specified as an array or as a comma-separated string of
#pod tags.
#pod
#pod =cut

has tags => (
    is => 'rw',
    isa => ArrayRef,
    default => sub { [] },
    coerce => sub {
        return [] unless $_[0];
        if ( !ref $_[0] ) {
            return [ split /\s*,\s*/, $_[0] ];
        }
        return $_[0];
    },
);

#pod =attr links
#pod
#pod     ---
#pod     links:
#pod         stylesheet:
#pod             - href: /theme/css/extra.css
#pod         alternate:
#pod             - href: http://example.com/blog/alternate
#pod               title: A contributed blog
#pod     ---
#pod
#pod Related links for this document. Links are used to build relationships
#pod to other web addresses. Link categories are named based on their
#pod relationship. Some possible categories are:
#pod
#pod =over 4
#pod
#pod =item stylesheet
#pod
#pod Additional stylesheets for the content of this document.
#pod
#pod =item script
#pod
#pod Additional scripts for the content of this document.
#pod
#pod =item alternate
#pod
#pod A link to the same document in another format or posted to another web site
#pod
#pod =back
#pod
#pod Each category contains an arrayref of hashrefs of L<link objects|Statocles::Link>.
#pod See the L<Statocles::Link|Statocles::Link> documentation for a full list of
#pod supported attributes. The most common attributes are:
#pod
#pod =over 4
#pod
#pod =item href
#pod
#pod The URL for the link.
#pod
#pod =item text
#pod
#pod The text of the link. Not needed for stylesheet or script links.
#pod
#pod =back
#pod
#pod =cut

has links => (
    is => 'rw',
    isa => LinkHash,
    default => sub { +{} },
    coerce => LinkHash->coercion,
);

#pod =attr images
#pod
#pod     ---
#pod     images:
#pod         title:
#pod             src: title.jpg
#pod             alt: A title image for this post
#pod         banner: banner.jpg
#pod     ---
#pod
#pod Related images for this document. These are used by themes to display
#pod images in appropriate templates. Each image has a category, like C<title>,
#pod C<banner>, or C<thumbnail>, mapped to an L<image object|Statocles::Image>.
#pod See the L<Statocles::Image|Statocles::Image> documentation for a full
#pod list of supported attributes. The most common attributes are:
#pod
#pod =over 4
#pod
#pod =item src
#pod
#pod The source path of the image. Relative paths will be resolved relative
#pod to this document.
#pod
#pod =item alt
#pod
#pod The alternative text to display if the image cannot be downloaded or
#pod rendered. Also the text to use for non-visual media.
#pod
#pod =back
#pod
#pod =cut

has images => (
    is => 'ro',
    isa => HashRef[InstanceOf['Statocles::Image']],
    default => sub { +{} },
    coerce => sub {
        my ( $ref ) = @_;
        my %img;
        for my $name ( keys %$ref ) {
            my $attrs = $ref->{ $name };
            if ( !ref $attrs ) {
                $attrs = { src => $attrs };
            }
            $img{ $name } = Statocles::Image->new(
                %{ $attrs },
            );
        }
        return \%img;
    },
);

#pod =attr date
#pod
#pod     ---
#pod     date: 2015-03-27
#pod     date: 2015-03-27 12:04:00
#pod     ---
#pod
#pod The date/time this document is for. For pages, this is the last modified date.
#pod For blog posts, this is the post's date.
#pod
#pod Should be in C<YYYY-MM-DD> or C<YYYY-MM-DD HH:MM:SS> format.
#pod
#pod =cut

has date => (
    is => 'rw',
    isa => DateTimeObj,
    coerce => DateTimeObj->coercion,
    predicate => 'has_date',
);

#pod =attr template
#pod
#pod     ---
#pod     template: /blog/recipe.html
#pod     ---
#pod
#pod The path to a template override for this document. If set, the L<document
#pod page|Statocles::Page::Document> will use this instead of the template provided
#pod by the application.
#pod
#pod The template path should not have the final extention (by default C<.ep>).
#pod Different template parsers will have different extentions.
#pod
#pod =cut

has template => (
    is => 'rw',
    isa => Maybe[ArrayRef[Str]],
    coerce => sub {
        return $_[0] if ref $_[0];
        return [ grep { $_ ne '' } split m{/}, $_[0] ];
    },
    predicate => 'has_template',
);

#pod =attr layout
#pod
#pod     ---
#pod     layout: /site/layout-dark.html
#pod     ---
#pod
#pod The path to a layout template override for this document. If set, the L<document
#pod page|Statocles::Page::Document> will use this instead of the layout provided
#pod by the application.
#pod
#pod The template path should not have the final extention (by default C<.ep>).
#pod Different template parsers will have different extentions.
#pod
#pod =cut

has layout => (
    is => 'rw',
    isa => Maybe[ArrayRef[Str]],
    coerce => sub {
        return $_[0] if ref $_[0];
        return [ grep { $_ ne '' } split m{/}, $_[0] ];
    },
    predicate => 'has_layout',
);

#pod =attr data
#pod
#pod     ---
#pod     data:
#pod       - Eggs
#pod       - Milk
#pod       - Cheese
#pod     ---
#pod     % for my $item ( @{ $self->data } ) {
#pod         <%= $item %>
#pod     % }
#pod
#pod Any kind of extra data to attach to this document, either array (like above),
#pod hash, string, or number, or combinations of all of these. This is available
#pod immediately in the document content, and later in the page template.
#pod
#pod Every document's content is parsed as a template. The C<data> attribute can be
#pod used in the template to allow for some structured data that would be cumbersome
#pod to have to mark up time and again.
#pod
#pod =cut

has data => (
    is => 'rw',
);

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

Statocles::Document - Base class for all Statocles documents

=head1 VERSION

version 0.073

=head1 DESCRIPTION

A Statocles::Document is the base unit of content in Statocles.
L<Applications|Statocles::App> take documents to build
L<pages|Statocles::Page>.

Documents are usually written as files, with the L<content|/content> in Markdown,
and the other attributes as frontmatter, a block of YAML at the top of the file.

An example file with frontmatter looks like:

    ---
    title: My Blog Post
    author: preaction
    links:
        stylesheet:
            - href: /theme/css/extra.css
    ---
    In my younger and more vulnerable years, my father gave me some

=head1 ATTRIBUTES

=head2 path

The path to this document. This is not settable from the frontmatter.

=head2 store

The Store this document comes from. This is not settable from the
frontmatter.

=head2 title

    ---
    title: My First Post
    ---

The title of this document. Used in the template and the main page
title. Any unsafe characters in the title (C<E<lt>>, C<E<gt>>, C<">, and
C<&>) will be escaped by the template, so no HTML allowed.

=head2 author

    ---
    author: preaction <doug@example.com>
    ---

The author of this document. Optional.

=head2 status

The publishing status of this document.  Optional. Statocles apps can
examine this to determine whether to turn a document into a page.  The
default value is C<published>; other reasonable values could include
C<draft> or C<private>.

=head2 content

The raw content of this document, in markdown. This is everything below
the ending C<---> of the frontmatter.

=head2 tags

    ---
    tags: recipe, beef, cheese
    tags:
        - recipe
        - beef
        - cheese
    ---

The tags for this document. Tags are used to categorize documents.

Tags may be specified as an array or as a comma-separated string of
tags.

=head2 links

    ---
    links:
        stylesheet:
            - href: /theme/css/extra.css
        alternate:
            - href: http://example.com/blog/alternate
              title: A contributed blog
    ---

Related links for this document. Links are used to build relationships
to other web addresses. Link categories are named based on their
relationship. Some possible categories are:

=over 4

=item stylesheet

Additional stylesheets for the content of this document.

=item script

Additional scripts for the content of this document.

=item alternate

A link to the same document in another format or posted to another web site

=back

Each category contains an arrayref of hashrefs of L<link objects|Statocles::Link>.
See the L<Statocles::Link|Statocles::Link> documentation for a full list of
supported attributes. The most common attributes are:

=over 4

=item href

The URL for the link.

=item text

The text of the link. Not needed for stylesheet or script links.

=back

=head2 images

    ---
    images:
        title:
            src: title.jpg
            alt: A title image for this post
        banner: banner.jpg
    ---

Related images for this document. These are used by themes to display
images in appropriate templates. Each image has a category, like C<title>,
C<banner>, or C<thumbnail>, mapped to an L<image object|Statocles::Image>.
See the L<Statocles::Image|Statocles::Image> documentation for a full
list of supported attributes. The most common attributes are:

=over 4

=item src

The source path of the image. Relative paths will be resolved relative
to this document.

=item alt

The alternative text to display if the image cannot be downloaded or
rendered. Also the text to use for non-visual media.

=back

=head2 date

    ---
    date: 2015-03-27
    date: 2015-03-27 12:04:00
    ---

The date/time this document is for. For pages, this is the last modified date.
For blog posts, this is the post's date.

Should be in C<YYYY-MM-DD> or C<YYYY-MM-DD HH:MM:SS> format.

=head2 template

    ---
    template: /blog/recipe.html
    ---

The path to a template override for this document. If set, the L<document
page|Statocles::Page::Document> will use this instead of the template provided
by the application.

The template path should not have the final extention (by default C<.ep>).
Different template parsers will have different extentions.

=head2 layout

    ---
    layout: /site/layout-dark.html
    ---

The path to a layout template override for this document. If set, the L<document
page|Statocles::Page::Document> will use this instead of the layout provided
by the application.

The template path should not have the final extention (by default C<.ep>).
Different template parsers will have different extentions.

=head2 data

    ---
    data:
      - Eggs
      - Milk
      - Cheese
    ---
    % for my $item ( @{ $self->data } ) {
        <%= $item %>
    % }

Any kind of extra data to attach to this document, either array (like above),
hash, string, or number, or combinations of all of these. This is available
immediately in the document content, and later in the page template.

Every document's content is parsed as a template. The C<data> attribute can be
used in the template to allow for some structured data that would be cumbersome
to have to mark up time and again.

=head1 SEE ALSO

=over 4

=item L<Statocles::Help::Content>

The content guide describes how to edit content in Statocles sites, which are
represented by Document objects.

=back

=head1 AUTHOR

Doug Bell <preaction@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2016 by Doug Bell.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
