Slovo

 view release on metacpan or  search on metacpan

lib/Slovo/Plugin/TagHelpers.pm  view on Meta::CPAN

package Slovo::Plugin::TagHelpers;
use Mojo::Base 'Mojolicious::Plugin::TagHelpers', -signatures;

use Scalar::Util 'blessed';
use Mojo::DOM::HTML 'tag_to_html';
use Mojo::Collection 'c';

my sub _select_box ($c, $name, $options, %attrs) {
  return $c->tag(
    div => class => "mui-select $name" => sub {
      my $label = $c->label_for($name => delete $attrs{label} // ucfirst $name);
      $c->param($name => delete $attrs{value})
        if exists $attrs{value} && !defined $c->param($name);
      return $label . ' ' . $c->select_field($name, $options, %attrs);
    });
}

my sub _checkboxes ($c, $name, $options, %attrs) {
  my $label = $c->label_for($name => delete $attrs{label} // ucfirst $name);
  return $c->tag(
    div => (class => "mui-textfield $name", %attrs) => sub {
      my $html = "";
      for my $check (@$options) {
        my $group_name = $check->[0];
        $check->[0] = $name;
        $html
          .= tag_to_html('label' => sub { $c->check_box(@$check) . " $group_name" }) . $/;
      }
      return $label . $/ . tag_to_html(div => (class => 'mui-checkbox') => sub {$html});
    });

}

my sub _html_substr ($c, $html, $selector, $chars) {
  state $html_dom = Mojo::DOM->new;

  # Split on two subsequent new lines and get the first five paragraphs but
  # only if the content is not HTML, (e. g. it is markdown).
  return c(split m|$/$/|, $html)->head(5)->map(sub ($txt) {
    $chars <= 0 && return '';

    # strip potential inline markup
    $txt =~ s/<[^>]+>?//g;
    my $html = '<p>' . substr($txt, 0, $chars) . '…</p>';
    $chars -= length($txt);
    return $html;
  })->join('') unless $html =~ /^<\w/;

  # Get the first 5 elements, matching $selector and prepare them for
  # displaying as text, until the targeted number of characters is reached.
  my $out = $html_dom->parse($html)->find($selector)->head(5)->map(sub ($el) {
    return '' unless $el;
    return '' if $chars <= 0;
    my $txt  = $el->all_text;
    my $html = tag_to_html($el->tag, %{$el->attr}, substr($txt, 0, $chars));
    $chars -= length($txt);
    return $html;
  })->join('');

  return $out;
}

my sub _format_body ($c, $celina) {
  my $id = 'celina_body_' . $celina->{data_format} . $celina->{id};
  if ($celina->{data_format} eq 'markdown') {
    my $body = $celina->{body} =~ s/\`/\\`/gr;
    return
        tag_to_html(div => (id => $id), sub { $celina->{body} })
      . $/
      . $c->javascript('/js/editormd/lib/marked.min.js')
      . $/
      . tag_to_html(
      script => sub {
        <<"JS";
document.getElementById('$id').innerHTML = marked(`$body`);
JS
      });
  }
  return tag_to_html(div => (id => $id), sub { $celina->{body} });
}

sub register ($self, $app, $config) {

  #initialise the base unless alredy initialised
  $self->SUPER::register($app) unless exists $app->renderer->helpers->{t};

  $app->helper(checkboxes  => \&_checkboxes);
  $app->helper(select_box  => \&_select_box);
  $app->helper(html_substr => \&_html_substr);
  $app->helper(format_body => \&_format_body);

  for my $h (qw(stylesheets javascripts)) {
    $app->helper(
      $h => sub {
        state $tag = $h =~ s/s$//r;
        if ($_[1]) {
          my $d = $app->defaults->{$h} //= [];
          push @$d, $_[0]->$tag($_[1]);
          return $_[0];



( run in 0.956 second using v1.01-cache-2.11-cpan-71847e10f99 )