App-WRT

 view release on metacpan or  search on metacpan

lib/App/WRT.pm  view on Meta::CPAN

      <title>${title_prefix} - ${title}</title>
    </head>

    <body>
    ${content}
    </body>

    </html>

Within templates, C<${foo}> will be replaced with the corresponding
configuration value.  C<${content}> will always be set to the content of the
current entry.

=head2 CONFIGURATION

Configuration is read from a F<wrt.json> in the directory where the C<wrt>
utility is invoked, or can (usually) be specified with the C<--config> option.

See F<example/wrt.json> for a sample configuration.

Under the hood, configuration is done by combining a hash called C<%default>
with values pulled out of the JSON file.  Most defaults can be overwritten
from the config file, but changing some would require writing Perl, since
they contain things like subroutine references.

=cut

=over

=item %default

Here's a verbatim copy of C<%default>, with some commentary about values.

    my %default = (
      root_dir       => '.',         # dir for wrt repository
      entry_dir      => 'archives',  # dir for entry files
      filter_dir     => 'filters',   # dir to contain filter scripts
      publish_dir    => 'public',    # dir to publish site to
      url_root       => "/",         # root URL for building links
      image_url_root => '',          # same for images
      template_dir   => 'templates', # dir for template files
      template       => 'default',   # template to use
      title          => '',          # current title (used in template)
      title_prefix   => '',          # a string to slap in front of titles
      stylesheet_url => undef,       # path to a CSS file (used in template)
      favicon_url    => undef,       # path to a favicon (used in template)
      feed_alias     => 'feed',      # what entry path should correspond to feed?
      feed_length    => 30,          # how many entries should there be in the feed?
      author         => undef,       # author name (used in template, feed)
      description    => undef,       # site description (used in template)
      content        => undef,       # place to stash content for templates
      default_entry  => 'new',       # what to display if no entry specified
      cache_includes => 0,           # should included files be cached in memory?

      # A license string for site content:
      license        => 'public domain',

      # A string value to replace all pages with (useful for occasional
      # situations where every page of a site should serve some other
      # content in-place, like Net Neutrality protest blackouts):
      overlay        => undef,

      # We'll show links for these, but not display them inline:
      binfile_expr   => qr/[.](tgz|zip|tar[.]gz|gz|txt|pdf)$/,
    );

=cut

my %default = (
  root_dir       => '.',         # dir for wrt repository
  root_dir_abs   => undef,       # for stashing absolute path to wrt repo
  entry_dir      => 'archives',  # dir for entry files
  filter_dir     => 'filters',   # dir to contain filter scripts
  publish_dir    => 'public',    # dir to publish site to
  url_root       => "/",         # root URL for building links
  image_url_root => '',          # same for images
  template_dir   => 'templates', # dir for template files
  template       => 'default',   # template to use
  title          => '',          # current title (used in template)
  title_prefix   => '',          # a string to slap in front of titles
  stylesheet_url => undef,       # path to a CSS file (used in template)
  favicon_url    => undef,       # path to a favicon (used in template)
  feed_alias     => 'feed',      # what entry path should correspond to feed?
  feed_length    => 30,          # how many entries should there be in feed?
  author         => undef,       # author name (used in template, feed)
  description    => undef,       # site description (used in template)
  content        => undef,       # place to stash content for templates
  default_entry  => 'new',       # what to display if no entry specified
  cache_includes => 0,           # should included files be cached in memory?

  # A license string for site content:
  license        => 'public domain',

  # A string value to replace all pages with (useful for occasional
  # situations where every page of a site should serve some other
  # content in-place, like Net Neutrality protest blackouts):
  overlay        => undef,

  # We'll show links for these, but not display them inline:
  binfile_expr   => qr/[.](tgz|zip|tar[.]gz|gz|txt|pdf)$/,
);

=item $default{entry_descriptions}

A hashref which contains a map of entry titles to entry descriptions.

=cut

# TODO: this has gotten more than a little silly.
$default{entry_descriptions} = {
  new => 'newest entries',
  all => 'all entries',
};

=item $default{title_cache}

A hashref which contains a cache of entry titles, populated by the renderer.

=cut

$default{title_cache} = { };

=back

=head2 METHODS AND INTERNALS

For no bigger than this thing is, the internals are convoluted.  (This is
because it's spaghetti code originally written in a now-archaic language by a
teenager who didn't know how to program.)

=over

=item new_from_file($config_file)

Takes a filename to pull JSON config data out of, and returns a new App::WRT
instance with the parameters set in that file.

=cut

sub new_from_file {
  my ($config_file) = @_;

  my $JSON = JSON->new->utf8->pretty;

  # Grab configuration from wrt.json or other file:
  my $config_hashref = $JSON->decode(file_get_contents($config_file));

  # Check for deprecated or removed configuration, and warn accordingly.
  # TODO: These are really user-facing errors, so Carp is probably the wrong
  #       tool for the job here.
  if ( defined $config_hashref->{entry_map} ) {
    carp(
      "Caution: wrt v7.0.0 and later no longer support entry_map.\n"
      . "Please check $config_file and remove this value."
    );
  }
  if ( defined $config_hashref->{embedded_perl} ) {

lib/App/WRT.pm  view on Meta::CPAN

populate an HTML blob for that stuff.

XXX: Here is where we put the list of pages for a given tag, but also maybe
other things about a page or its properties.  There should be a template /
partial involved.

=cut

sub populate_metadata_cache {
  my $self = shift;

  my %metadata_html_cache;
  foreach my $entry ($self->{entries}->all()) {
    my $result = '';

    my $tag_for_this_entry = 'tag.' . join('.', split('/', $entry));
    my (@tagged_entries) = $self->{entries}->by_prop($tag_for_this_entry);
    my (@alpha_entries, @dated_entries);
    for (@tagged_entries) {
      if (m{^\d}) {
        push @dated_entries, $_;
      } else {
        push @alpha_entries, $_;
      }
    }

    if (@tagged_entries) {
      $result .= "<h1>entries tagged " . encode_entities($entry)
               . "</h1>\n\n<table class=tags>";

      # Things starting with letters first, then things starting with digits:
      foreach my $tagged_entry (@alpha_entries, reverse @dated_entries) {
        $result .= table_row(
          table_cell(
            a($tagged_entry, { href => $self->{url_root} . "$tagged_entry" })
          ),
          table_cell(
            encode_entities($self->get_title($tagged_entry))
          )
        );
        $result .= "\n";
      }
      $result .= "</table>";
    }

    $metadata_html_cache{$entry} = $result;
  }

  $self->{metadata_html_cache} = \%metadata_html_cache;
}

=item display($entry1, $entry2, ...)

Return a string containing the given entries, which are in the form of
date/entry strings. If no parameters are given, default to C<default_entry>.

display() expands aliases ("new" and "all", for example) as necessary, collects
entry content and metadata from the pre-rendered HTML caches, and wraps
everything up in the template.

If C<overlay> is set, will return the value of overlay regardless of options.
(This is useful for hackily replacing every page in a site with a single blob
of HTML, for example if you're participating in some sort of blackout or
something.)

=cut

sub display {
  my $self = shift;
  my (@entries) = @_;

  return $self->{overlay} if defined $self->{overlay};

  # If no entries are defined, either...
  if ($self->{entries}->is_extant('index')) {
    # Fall back to the existing index file:
    $entries[0] = 'index';
  } else {
    # Or use the default:
    $entries[0] //= $self->{default_entry};
  }

  # Title and navigation for template:
  $self->{page_navigation} = '';
  $self->{title} = join ' ', map { encode_entities($_) } @entries;

  if (scalar @entries == 1) {
    # We've got a single path - it could be an alias that'll expand, or it
    # could be an individual entry.  See what can be done with navigation
    # and title:
    $self->{page_navigation} = $self->page_navigation($entries[0]);
    $self->{title} = encode_entities($self->get_title($entries[0]));
  }

  # Expand on any aliases:
  @entries = map { $self->expand_alias($_) } @entries;

  # To be accessed as ${content} in the template below:
  $self->{content} = join '', map {
    $self->{html_cache}{$_}
    . '<div class=entry-metadata>'
    . $self->{metadata_html_cache}{$_}
    . '</div>'
  } @entries;

  # TODO: There may be an optimization to be had below in only running
  # line_parse() against the template when the source is stashed.  This would
  # also lead to confusing weirdness if the template contained any special
  # markup besides an <include> or relied on any side effects of embedded Perl
  # code.  For now, I'm leaving it alone.

  # Evaluate the template much like an entry:
  # Eventually, the eval_perl() call should probably be hoisted up here and
  # only used for templates.
  return $self->line_parse($self->{template_source}, $self->{template_path});
}

=item handle($entry)

Return the text of an individual entry:

  nnnn/[nn/nn/]doc_name - a document within a day.
  nnnn/nn/nn            - a specific day.
  nnnn/nn               - a month.
  nnnn                  - a year.
  doc_name              - a document in the root directory.

=cut

sub handle {
  my ($self, $entry) = @_;



( run in 0.647 second using v1.01-cache-2.11-cpan-7fcb06a456a )