/usr/local/CPAN/hub-standard/Hub/Parse/HtmlParser.pm


package Hub::Parse::HtmlParser;
use strict;
use Hub qw/:lib/;
our $has_imagelib;

BEGIN {
  eval 'use Image::Size qw(imgsize)';
  our $has_imagelib = !$@;
}

push our @ISA, qw(Hub::Parse::StandardParser);

our %EVALUATORS;

sub get_evaluator {
  return defined $EVALUATORS{$_[1]}
    ? $EVALUATORS{$_[1]}
    : &Hub::Parse::StandardParser::get_evaluator(@_);
}

$EVALUATORS{'url'} = sub {
  my ($self, $params, $result) = @_;
  my ($outer_str, $fields, $pos, $text, $parents, $valdata) = @$params;
  my ($opts, %directive) = Hub::opts($fields);
  $result->{'value'} = '';
  my $literal = $directive{'url'};

# Get the site URL.  This is...
# my $script_filename = $$Hub{'/sys/ENV/SCRIPT_FILENAME'};
# my $relative_filename = substr $script_filename, length($$Hub{'/sys/ENV/WORKING_DIR'});
#warn "script_filename:    $script_filename\n";

  my $relative_filename = Hub::getaddr($ENV{'SCRIPT_FILENAME'});
  my $script_name  = $$Hub{'/sys/ENV/SCRIPT_NAME'};
  my $site_url = substr($script_name, 0, - length($relative_filename)) || '';

#warn "relative_filename:  $relative_filename\n";
#warn "script_name:        $script_name\n";
#warn "site_url:           $site_url\n";

#warn "--url--: $literal\n";
  if ($$opts{'relative'}) {
    # Figure out script directory
    my $script_dir = Hub::getpath($$Hub{'/sys/ENV/SCRIPT_FILENAME'});
    my $work_dir = $$Hub{'/sys/ENV/WORKING_DIR'};
    if (index($script_dir, $work_dir) == 0 ) {
#warn "   trim: $work_dir\n";
      $script_dir = substr($script_dir, length($work_dir));
    }
    if ($script_dir eq $work_dir) {
      $script_dir = '/';
    }
    $script_dir ||= '/';
    # Find the relative path
    my $relative_path = Hub::relpath($literal, $script_dir);
#warn "   from: $script_dir\n";
#warn "     to: $literal\n";
#warn "      =: $relative_path\n";
    $$result{'value'} = $relative_path;
  } else {
    $$result{'value'} = $literal =~ /^\// ? $site_url . $literal : $literal;
  }
};

$EVALUATORS{'image'} = sub {
  my ($self, $params, $result) = @_;
  my ($outer_str, $fields, $pos, $text, $parents, $valdata) = @$params;
  my ($opts, %directive) = Hub::opts($fields);
  $result->{'value'} = '';
  my $relpath = $directive{'image'} || '';
  my %args = %directive; # copy
  my $path = Hub::srcpath($relpath) || $relpath;
  unless ($path) {
    warn "Image path not found: $args{'image'}";
    return;
  }
  delete $args{'image'};
  if ($has_imagelib) {
#   my ($x,$y,$error) = imgsize($path);
    my ($x,$y) = _getdims($path, -opts => $opts);
    $args{'width'} ||= $x;
    $args{'height'} ||= $y;
  }
  $args{'src'} = $$self{'var_begin'}
    . "url \"$relpath\"" . $$self{'var_end'};
  $$result{'value'} = '<img ' . Hub::hashtoattrs(\%args) . '/>';
};

# ------------------------------------------------------------------------------
# _getdims - Get image dimensions
# _getdims $path, [options]
#
# options:
# 
#   -max_x=n    Maximum width
#   -max_y=n    Maximum height
#   -min_x=n    Minimum width
#   -min_y=n    Minimum height
#
# my ($w,$h) = _getdims( "/images/laura.jpg", -max_x => 50, -max_y => 50 );
# ------------------------------------------------------------------------------

sub _getdims {

  my ($opts, $file) = Hub::opts(\@_, {
    'max_x' => 0,
    'min_x' => 0,
    'max_y' => 0,
    'min_y' => 0,
  });

  my $nx      = 0;
  my $ny      = 0;
  my $w       = 0;
  my $h       = 0;

  ($nx,$ny) = imgsize($file);
  $w = $nx;
  $h = $ny;

  # Expand
  if( $nx > 0 && $$opts{'min_x'} > 0 ) {
    if( $nx < $$opts{'min_x'} ) {
      my $ratio = $ny/$nx;
      my $expandX = $$opts{'min_x'} - $nx;
      my $expandY = int($expandX*$ratio);
      $w = $nx + $expandX;
      $h = $ny + $expandY;
      $nx = $w;
      $ny = $h;
    }#if
  }#if
  if( $ny > 0 && $$opts{'min_y'} > 0 ) {
    if( $ny < $$opts{'min_y'} ) {
      my $ratio = $nx/$ny;
      my $expandY = $$opts{'min_y'} - $ny;
      my $expandX = int($expandY*$ratio);
      $w = $nx + $expandX;
      $h = $ny + $expandY;
      $nx = $w;
      $ny = $h;
    }#if
  }#if

  # Reduce
  if( $$opts{'max_x'} > 0 ) {
    if( $nx > $$opts{'max_x'} ) {
      my $ratio = $ny/$nx;
      my $reduceX = $nx - $$opts{'max_x'};
      my $reduceY = int($reduceX*$ratio);
      $w = $nx - $reduceX;
      $h = $ny - $reduceY;
      $nx = $w;
      $ny = $h;
    }#if
  }#if
  if( $$opts{'max_y'} > 0 ) {
    if( $ny > $$opts{'max_y'} ) {
      my $ratio = $nx/$ny;
      my $reduceY = $ny - $$opts{'max_y'};
      my $reduceX = int($reduceY*$ratio);
      $w = $nx - $reduceX;
      $h = $ny - $reduceY;
      $nx = $w;
      $ny = $h;
    }#if
  }#if

  return ($nx, $ny);
}#_getdims


$EVALUATORS{'jsvar'} = sub {
  my ($self, $params, $result) = @_;
  my ($outer_str, $fields, $pos, $text, $parents, $valdata) = @$params;
  my ($opts, %directive) = Hub::opts($fields);
  my $value = $self->get_value($directive{'jsvar'}, $valdata, $fields);
  return unless defined $value;
  $$result{'value'} = _jsvar($value, $self, $valdata);
};

sub _jsvar {
  my $item = shift;
  return isa($item, 'HASH')
    ?  '{' . join(', ', _jsvar_hash($item, @_)) . '}'
    : isa($item, 'ARRAY')
      ? '[' . join(', ', _jsvar_array($item, @_)) . ']'
      : "'" . Hub::jsstr(_jsvar_scalar($item, @_)) . "'";
}

sub _jsvar_hash {
  my $item = shift;
  my @args = @_;
  map {Hub::safestr($_) . ": " . _jsvar($$item{$_}, @args)} keys %$item
}

sub _jsvar_array {
  my $item = shift;
  my @args = @_;
  map {_jsvar($_, @args)} @$item;
}

sub _jsvar_scalar {
  my ($item, $self, $valdata) = @_;
  my $value = $self->_populate(-text => $item, @$valdata);
  $self->{'*depth'}--;
  return $$value;
};


1;