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 = '
' . substr($txt, 0, $chars) . '…
'; $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]; } return join $/, @{$_[0]->stash->{$h} //= []}; }); } return $self; } 1; =encoding utf8 =head1 NAME Slovo::Plugin::TagHelpers - additional and advanced tag helpers =head1 SYNOPSIS <%= select_box page_type => [map {[$_=>$_]}], @$page_types] required => 1, label => 'Page type' %> =head1 DESCRIPTION Slovo::Plugin::TagHelpers extends L