App-Followme

 view release on metacpan or  search on metacpan

lib/App/Followme/FormatPage.pm  view on Meta::CPAN


        } elsif ($token =~ /^<!--\s*endsection\s+(.*?)-->/) {
            my ($endname) = $self->parse_blockname($1);
            die "Unmatched ($token)\n"
                if $blockname eq '' || $blockname ne $endname;

            $block .= $token;
            $block_handler->($blockname, $locality, $block);

            $block = '';
            $blockname = '';

        } else {
            if ($blockname) {
                $block .= $token;
            } else {
                $prototype_handler->($token);
            }
        }
    }

    die "Unmatched block (<!-- section $blockname -->)\n" if $blockname;
    return;
}

#----------------------------------------------------------------------
# Extract named blocks from a page

sub parse_page {
    my ($self, $page) = @_;

    my $blocks = {};
    my $block_handler = sub {
        my ($blockname, $locality, $blocktext) = @_;
        if (exists $blocks->{$blockname}) {
            die "Duplicate block name ($blockname)\n";
        }
        $blocks->{$blockname} = $blocktext;
        return;
    };

    my $prototype_handler = sub {
        return;
    };

    $self->parse_blocks($page, $block_handler, $prototype_handler);
    return $blocks;
}

#----------------------------------------------------------------------
# Initialize the extension

sub setup {
    my ($self) = @_;

    $self->{extension} = $self->{web_extension};
    return;
}

#----------------------------------------------------------------------
# Determine if page matches prototype or needs to be updated

sub unchanged_prototype {
    my ($self, $prototype, $page, $prototype_path) = @_;

    my $prototype_checksum =
        $self->checksum_prototype($prototype, $prototype_path);

    my $page_checksum =
        $self->checksum_prototype($page, $prototype_path);

    my $unchanged;
    if ($prototype_checksum eq $page_checksum) {
        $unchanged = 1;
    } else {
        $unchanged = 0;
    }

    return $unchanged;
}

#----------------------------------------------------------------------
# Update file using prototype

sub update_file {
    my ($self, $file, $prototype, $prototype_path) = @_;

    my $page = fio_read_page($file);
    return unless defined $page;

    # Check for changes before updating page
    return 0 if $self->unchanged_prototype($prototype, $page, $prototype_path);

    $page = $self->update_page($page, $prototype, $prototype_path);

    my $modtime = fio_get_date($file);
    fio_write_page($file, $page);
    fio_set_date($file, $modtime);

    return 1;
}

#----------------------------------------------------------------------
# Perform all updates on the directory

sub update_folder {
    my ($self, $folder, $prototype_file) = @_;

    my $index_file = $self->to_file($folder);
    my ($prototype_path, $prototype);
    my $modtime = fio_get_date($folder);

    my $files = $self->{data}->build('files_by_mdate_reversed', $index_file);
    my $file = shift(@$files);

    if ($file) {
        # The first update uses a file from the  directory above
        # as a prototype, if one is found

        $prototype_file ||= $self->find_prototype($folder, 1);

lib/App/Followme/FormatPage.pm  view on Meta::CPAN


    my $block_handler = sub {
        my ($blockname, $locality, $blocktext) = @_;
        if (exists $blocks->{$blockname}) {
            if (exists $prototype_path->{$locality}) {
                push(@$output, $blocktext);
            } else {
                push(@$output, $blocks->{$blockname});
            }
            delete $blocks->{$blockname};
        } else {
            push(@$output, $blocktext);
        }
        return;
    };

    my $prototype_handler = sub {
        my ($blocktext) = @_;
        push(@$output, $blocktext);
        return;
    };

    $self->parse_blocks($prototype, $block_handler, $prototype_handler);

    if (%$blocks) {
        my $names = join(' ', sort keys %$blocks);
        die "Unused blocks ($names)\n";
    }

    return join('', @$output);
}

1;
__END__

=encoding utf-8

=head1 NAME

App::Followme::FormatPages - Modify pages in a directory to match a prototype

=head1 SYNOPSIS

    use App::Followme::FormatPages;
    my $formatter = App::Followme::FormatPages->new($configuration);
    $formatter->run($directory);

=head1 DESCRIPTION

App::Followme::FormatPages updates the web pages in a folder to match the most
recently modified page. Each web page has sections that are different from other
pages and other sections that are the same. The sections that differ are
enclosed in html comments that look like

    <!-- section name-->
    <!-- endsection name -->

and indicate where the section begins and ends. When a page is changed, this
module checks the text outside of these comments. If that text has changed. the
other pages on the site are also changed to match the page that has changed.
Each page updated by substituting all its named blocks into corresponding block
in the changed page. The effect is that all the text outside the named blocks
are updated to be the same across all the web pages.

Updates to the named block can also be made conditional by adding an "in" after
the section name. If the folder name after the "in" is included in the
prototype_path hash, then the block tags are ignored, it is as if the block does
not exist. The block is considered as part of the constant portion of the
prototype. If the folder is not in the prototype_path, the block is treated as
any other block and varies from page to page.

    <!-- section name in folder -->
    <!-- endsection name -->

Text in conditional blocks can be used for navigation or other sections of the
page that are constant, but not constant across the entire site.

=head1 CONFIGURATION

The following parameters are used from the configuration:

=over 4

=item exclude_index

If this value is non-zero, the index page in a folder will not change when other
pages in its folder change and vice versa. The default value of this variable is 
zero.

=item data_pkg

The name of the module that processes web files. The default value is
'App::Followme::WebData'.

=item web_extension

The extension used by web pages. The default value is html

=back

=head1 LICENSE

Copyright (C) Bernie Simon.

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

=head1 AUTHOR

Bernie Simon E<lt>bernie.simon@gmail.comE<gt>

=cut



( run in 2.100 seconds using v1.01-cache-2.11-cpan-5a3173703d6 )