2022-11-09 13:31:58 +01:00
|
|
|
package BurguillosInfo::Posts;
|
|
|
|
|
|
|
|
use v5.34.1;
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
2022-11-13 02:01:24 +01:00
|
|
|
use Data::Dumper;
|
|
|
|
|
2022-11-09 13:31:58 +01:00
|
|
|
use Const::Fast;
|
|
|
|
use Mojo::DOM;
|
|
|
|
use Path::Tiny;
|
|
|
|
use DateTime::Format::ISO8601;
|
2022-11-13 02:01:24 +01:00
|
|
|
use SVG;
|
|
|
|
use Capture::Tiny qw/capture/;
|
2022-11-09 13:31:58 +01:00
|
|
|
|
|
|
|
const my $CURRENT_FILE => __FILE__;
|
|
|
|
const my $POSTS_DIR =>
|
|
|
|
path($CURRENT_FILE)->parent->parent->parent->child('content/posts');
|
|
|
|
|
|
|
|
my $iso8601 = DateTime::Format::ISO8601->new;
|
|
|
|
|
|
|
|
my $cached_posts_by_category;
|
|
|
|
my $cached_posts_by_slug;
|
|
|
|
|
|
|
|
sub new {
|
|
|
|
return bless {}, shift;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub Retrieve {
|
|
|
|
if ( defined $cached_posts_by_category && defined $cached_posts_by_slug ) {
|
|
|
|
return ( $cached_posts_by_category, $cached_posts_by_slug );
|
|
|
|
}
|
|
|
|
$cached_posts_by_category = {};
|
|
|
|
$cached_posts_by_slug = {};
|
2022-11-10 23:49:13 +01:00
|
|
|
for my $post_file ( sort { $b cmp $a } $POSTS_DIR->children ) {
|
2022-11-09 13:31:58 +01:00
|
|
|
warn "Bad file $post_file, omiting...", next
|
|
|
|
if !-f $post_file || $post_file !~ /\.xml$/;
|
|
|
|
my $dom = Mojo::DOM->new( $post_file->slurp_utf8 );
|
|
|
|
my $title = $dom->at(':root > title')->text
|
|
|
|
or die "Missing title at $post_file.";
|
|
|
|
my $author = $dom->at(':root > author')->text
|
|
|
|
or die "Missing author at $post_file.";
|
|
|
|
my $date = $dom->at(':root > date')->text
|
|
|
|
or die "Missing date at $post_file.";
|
|
|
|
my $ogdesc = $dom->at(':root > ogdesc')->text
|
|
|
|
or die "Missing ogdesc at $post_file";
|
|
|
|
my $category = $dom->at(':root > category')->text
|
|
|
|
or die "Missing category at $post_file.";
|
|
|
|
my $slug = $dom->at(':root > slug')->text
|
|
|
|
or die "Missing slug at $post_file.";
|
|
|
|
my $content = $dom->at(':root > content')->content
|
|
|
|
or die "Missing content at $post_file.";
|
|
|
|
|
|
|
|
my $post = {
|
|
|
|
title => $title,
|
|
|
|
author => $author,
|
|
|
|
date => $date,
|
|
|
|
ogdesc => $ogdesc,
|
|
|
|
category => $category,
|
|
|
|
slug => $slug,
|
|
|
|
content => $content,
|
|
|
|
};
|
2022-11-13 02:01:24 +01:00
|
|
|
$cached_posts_by_category->{$category} //= [];
|
2022-11-09 13:31:58 +01:00
|
|
|
my $category_posts = $cached_posts_by_category->{$category};
|
2022-11-13 02:01:24 +01:00
|
|
|
$cached_posts_by_slug->{$slug} = $post;
|
|
|
|
push @$category_posts, $post;
|
|
|
|
}
|
|
|
|
return ( $cached_posts_by_category, $cached_posts_by_slug );
|
|
|
|
}
|
|
|
|
|
|
|
|
sub PostPreviewOg {
|
|
|
|
my $self = shift;
|
|
|
|
my $post = shift;
|
|
|
|
my $title = $post->{title};
|
|
|
|
my $content = $post->{content};
|
|
|
|
my $dom = Mojo::DOM->new($content);
|
|
|
|
$content = $dom->all_text;
|
|
|
|
|
|
|
|
my @content_divided_in_lines = split /\n/, $content;
|
|
|
|
my @new_content;
|
2022-11-13 03:53:58 +01:00
|
|
|
my $n_chars_per_line = 70;
|
2022-11-13 02:01:24 +01:00
|
|
|
|
|
|
|
for my $line (@content_divided_in_lines) {
|
|
|
|
if ( length($line) <= $n_chars_per_line ) {
|
|
|
|
push @new_content, $line;
|
|
|
|
next;
|
|
|
|
}
|
2022-11-13 03:53:58 +01:00
|
|
|
my $last_word = '';
|
2022-11-13 02:01:24 +01:00
|
|
|
while ( $line =~ /(.{1,${n_chars_per_line}})/g ) {
|
2022-11-13 03:53:58 +01:00
|
|
|
my $new_line = $last_word.$1;
|
|
|
|
$new_line =~ s/(\S*)$//;
|
|
|
|
$last_word = $1;
|
2022-11-13 02:01:24 +01:00
|
|
|
push @new_content, $new_line;
|
|
|
|
}
|
2022-11-13 03:53:58 +01:00
|
|
|
if ($last_word) {
|
|
|
|
$new_content[$#new_content] .= $last_word;
|
|
|
|
}
|
2022-11-13 02:01:24 +01:00
|
|
|
}
|
2022-11-13 03:53:58 +01:00
|
|
|
|
2022-11-13 02:01:24 +01:00
|
|
|
my $svg = $self->_GenerateSVGPostPreview( $title, \@new_content );
|
|
|
|
my ($stdout) = capture {
|
|
|
|
open my $fh, '|-', qw{convert /dev/stdin png:fd:1};
|
|
|
|
binmode ':utf8', $fh;
|
|
|
|
print $fh $svg;
|
|
|
|
close $fh;
|
|
|
|
};
|
|
|
|
return $stdout;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub _GenerateSVGPostPreview {
|
|
|
|
my $self = shift;
|
|
|
|
my $title = shift;
|
|
|
|
my $content = shift;
|
|
|
|
my @content = @$content;
|
2022-11-13 02:26:27 +01:00
|
|
|
my $svg = SVG->new( width => 1200, height => 627 );
|
2022-11-13 02:01:24 +01:00
|
|
|
$svg->rect(
|
|
|
|
x => 0,
|
|
|
|
y => 0,
|
|
|
|
width => 1200,
|
|
|
|
height => 50,
|
|
|
|
style => { fill => 'blueviolet' }
|
|
|
|
);
|
|
|
|
$svg->rect(
|
|
|
|
x => 0,
|
|
|
|
y => 50,
|
|
|
|
width => 1200,
|
2022-11-13 02:26:27 +01:00
|
|
|
height => 627,
|
2022-11-13 02:01:24 +01:00
|
|
|
style => { fill => '#F8F8FF' }
|
|
|
|
);
|
|
|
|
|
|
|
|
my $group = $svg->group(
|
|
|
|
id => 'group',
|
|
|
|
style => {
|
|
|
|
font => 'Arial',
|
|
|
|
'font-size' => 30,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
$group->text(
|
|
|
|
x => 10,
|
|
|
|
y => 40,
|
|
|
|
style => { 'font-size' => 50, fill => '#f2eb8c' }
|
|
|
|
)->cdata('Burguillos.info');
|
|
|
|
|
|
|
|
$group->text(
|
|
|
|
x => 10,
|
|
|
|
y => 100,
|
|
|
|
style => { 'font-size' => 50 }
|
|
|
|
)->cdata($title);
|
|
|
|
|
|
|
|
my $n = 0;
|
|
|
|
for my $line (@content) {
|
|
|
|
$group->text(
|
|
|
|
x => 10,
|
|
|
|
y => 140 + ( 30 * $n ),
|
|
|
|
style => { 'font-size' => 38 }
|
|
|
|
)->cdata($line);
|
|
|
|
$n++;
|
2022-11-09 13:31:58 +01:00
|
|
|
}
|
2022-11-13 02:01:24 +01:00
|
|
|
return $svg->xmlify;
|
2022-11-09 13:31:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
1;
|