use strictures 1; package Mojito; $Mojito::VERSION = '0.25'; use Moo; use Path::Class; use File::Spec; use 5.010; use Data::Dumper::Concise; extends 'Mojito::Page'; =head1 NAME Mojito - A Web Document System =head1 SYNOPSIS use Mojito::Model::Config; my $mojito = Mojito->new(config => Mojito::Model::Config->new->config); my $page_id = '123456781234567812345678'; my $rendered_page = $mojito->view_page({id => $page_id}); # You might want to checkout one of the applications in app/ # For example: 'plackup -Ilib' starts up a Web::Simple instance of Mojito =head1 DESCRIPTION Mojito is a web document system that enables individuals to easily author HTML5 compliant documents. It provides a source editor for various markup languages along with a near realtime view pane. It allows for the intermixing of different source formats. =head1 Attributes =head2 base_url Base of the application used for creating internal links. =cut has base_url => ( is => 'rw', ); =head2 username Authenticated (Digest Auth) user name (aka REMOTE_USER) =cut has username => ( is => 'rw', ); has bench_fixture => ( is => 'ro', lazy => 1, builder => '_build_bench_fixture'); =head1 Methods =head2 create_page Create a new page and return the url to redirect to, namely the page in edit mode. We might change this to view mode if demand persuades. =cut sub create_page { my ( $self, $params ) = @_; # We need to get some content into the delegatee $self->parser->page($params->{content}); my $page_struct = $self->page_structure; # Load some parts to the page_struct $page_struct->{default_format} = $params->{wiki_language}; $page_struct->{page_html} = $self->render_page($page_struct); $page_struct->{body_html} = $self->render_body($page_struct); $page_struct->{title} = $self->intro_text( $page_struct->{body_html} ); if ($params->{public}) { $page_struct->{public} = 1; } my $id = $self->create($page_struct); $params->{id} = $id; # Put into repo $params->{username} = $self->username; $self->commit_page($page_struct, $params); return $self->base_url . 'page/' . $id . '/edit'; } =head2 preview_page AJAX preview of a page (parse and render, save when button pressed) =cut sub preview_page { my ( $self, $params ) = @_; $self->parser->page($params->{content}); $self->parser->default_format($params->{wiki_language}); my $page_struct = $self->page_structure; if ( $params->{extra_action} && ( $params->{extra_action} eq 'save' ) && ( $params->{'mongo_id'} ) ) { $page_struct->{page_html} = $self->render_page($page_struct); $page_struct->{body_html} = $self->render_body($page_struct); $page_struct->{title} = $self->intro_text( $page_struct->{body_html} ); $self->update( $params->{'mongo_id'}, $page_struct ); } elsif ( $params->{'mongo_id'} ) { # Auto update this stuff so the user doesn't have to even think about clicking save button # TODO: add title, page and body html to page_struct like above. # Do we even need these two branches given that we're autosaving now. # TODO: on new page, insert to get an id then update to that from the start $page_struct->{title} = $params->{page_title}||'no title'; $self->update( $params->{'mongo_id'}, $page_struct ); } my $rendered_content = $self->render_body($page_struct); my $response_href = { rendered_content => $rendered_content, message => $page_struct->{message} }; return $response_href; } =head2 update_page Update a page given: content, id and base_url =cut sub update_page { my ( $self, $params ) = @_; $self->parser->page($params->{content}); $self->parser->default_format($params->{wiki_language}); my $page = $self->page_structure; # Store rendered parts as well. May as well until proven wrong. $page->{page_html} = $self->render_page($page); $page->{body_html} = $self->render_body($page); $page->{title} = $self->intro_text( $page->{body_html} ); # Add a feed if there is such a param if (my $feeds = $params->{feeds}) { # Allow : to separate multiple feeds. e.g. ?feeds=ironman:chatterbox my @feeds = split ':', $feeds; $page->{feeds} = [@feeds]; # A document that is part of a feed is considered public by default $page->{public} = 1; } if ($params->{public}) { $page->{public} = 1; } # Update the list of collections to which this doc belongs $self->collector->editer->update_collection_membership($params); # Save page to db $self->update( $params->{id}, $page ); # Commit revison to git repo # add username to params so it can used in the commit $params->{username} = $self->username; $self->commit_page($page, $params); return $self->base_url . 'page/' . $params->{id}; } =head2 edit_page_form Present the form with a page ready to be edited. =cut sub edit_page_form { my ( $self, $params ) = @_; my $page = $self->read( $params->{id} ); my $rendered_content = $self->render_body($page); return $self->fillin_edit_page( $page, $rendered_content, $params->{id} ); } =head2 view_page Given a page id, we retrieve its page from the db and return the HTML form of the page to the browser. =cut sub view_page { my ( $self, $params ) = @_; my $page = $self->read( $params->{id} ); my $rendered_page = $self->render_page($page); my $links = $self->get_recent_links; my $collections = $self->view_collections_index; # Change class on view_area when we're in view mode. $rendered_page =~ s/(/$1 class="view_area_view_mode">/si; # Fill-in recent area $rendered_page =~ s/()<\/section>/$1${links}<\/section>/si; # Fill-in collections area $rendered_page =~ s/()<\/section>/$1${collections}<\/section>/si; return $rendered_page; } =head2 view_page_public Given a page id, we retrieve its page from the db and return the HTML form of the page to the browser. This method is much like the view_page() method is setup for public pages (ones that do not require authentication). =cut sub view_page_public { my ( $self, $params ) = @_; my $page = $self->read( $params->{id} ); return "Page is not public" if not $page->{public}; # TODO: Use body_html unless otherwise specified # return $self->wrap_page($page->{body_html}, $page->{title}); return $self->wrap_page($self->render_body($page), $page->{title}); } =head2 view_page_collected Given a page id and a collection id we retrieve the collected page source from the db and return it as an HTML rendered page to the browser. This method is much like the view_page() method, but is setup for viewing pages in a collection with a collection navigation: next, previous, index (toc) =cut sub view_page_collected { my ( $self, $params ) = @_; my $page = $self->read( $params->{page_id} ); my $rendered_page = $self->render_page($page); # Change class on view_area when we're in view mode. $rendered_page =~ s/(/$1 class="view_area_view_mode">/si; # Strip out Edit and New links (even though they are Auth::Digest Protected) # Remove edit, new links and the recent area if(not $self->config->{username}) { $rendered_page =~ s/