Skip to content

Commit

Permalink
New module for Gemtext format
Browse files Browse the repository at this point in the history
  • Loading branch information
gemmaro committed Feb 7, 2024
1 parent 49f6485 commit c8294c3
Show file tree
Hide file tree
Showing 9 changed files with 452 additions and 0 deletions.
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ __ __/ _ \|___ / |
\ V /| |_| | / / | |
\_/ \___(_)_/ |_| (not released yet)

Gemtext:
* New module (GitHub's #466) [gemmaro].

=======================================================================
___ _____ ___
__ __/ _ \|___ / _ \
Expand Down
7 changes: 7 additions & 0 deletions doc/po4a.7.pod
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,13 @@ requirements to become an official GNU project). The support for
L<Locale::Po4a::Texinfo(3pm)|Texinfo> in po4a is still at the beginning.
Please report bugs and feature requests.

=item gemtext (very highly experimental parser)

The native plain text format of the Gemini protocol. The extension
".gmi" is commonly used. Support for this module in po4a is still in
its infancy. If you find anything, please file a bug or feature
request.

=item Others supported formats

Po4a can also handle some more rare or specialized formats, such as the
Expand Down
193 changes: 193 additions & 0 deletions lib/Locale/Po4a/Gemtext.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#!/usr/bin/env perl -w

# Po4a::Gemtext.pm
#
# extract and translate translatable strings from a Gemtext documents
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
########################################################################

require Exporter;

package Locale::Po4a::Gemtext;

use 5.006;
use strict;
use warnings;

use vars qw(@ISA @EXPORT @AUTOLOAD);
@ISA = qw(Locale::Po4a::TransTractor);
@EXPORT = qw();

use Locale::Po4a::TransTractor qw(process new);
use Locale::Po4a::Common;

=encoding UTF-8
=head1 NAME
Locale::Po4a::Gemtext - convert Gettext documents from/to PO files.
=head1 DESCRIPTION
The po4a (PO for anything) project goal is to ease translations (and more
interestingly, the maintenance of translations) using gettext tools on
areas where they were not expected like documentation.
Locale::Po4a::Gemtext is a module to help the translation of Gemtext documents into
other [human] languages.
=cut

sub initialize { }

sub parse {
my $self = shift;

my ( $line, $ref ) = $self->shiftline();

while ( defined($line) ) {
chomp($line);

$self->parse_heading( $line, $ref )
or $self->parse_preformatted_text( $line, $ref )
or $self->parse_list( $line, $ref )
or $self->parse_quote( $line, $ref )
or $self->parse_link( $line, $ref )
or $self->pushline( $self->translate( $line, $ref, "paragraph" ) . "\n" );

( $line, $ref ) = $self->shiftline();
}
}

sub parse_heading() {
my $self = shift;
my $line = shift;
my $ref = shift;

$line =~ m/^(#{1,3}) *(.+)/ or return;
my $level = $1;
my $content = $2;

$self->pushline( "$level " . $self->translate( $content, $ref, "heading $level" ) . "\n" );

return 1;
}

sub parse_preformatted_text() {
my $self = shift;
my $line = shift;
my $ref = shift;

$line =~ m/^(``` *)(.*)/ or return;
my $prefix = $1;
my $content = $2;

my $toggle_line = $prefix;
$toggle_line .= $self->translate( $content, $ref, "alt text" ) if $content;
$self->pushline("$toggle_line\n");

my $paragraph;
( $line, $ref ) = $self->shiftline();

while ( defined($line) ) {
chomp($line);

if ( $line =~ m/^```/ ) {
$self->pushline( $self->translate( $paragraph, $ref, "preformatted text" ) . "\n" );
$self->pushline("$line\n");

return 1;
}

if ($paragraph) {
$paragraph .= "\n$line";
} else {
$paragraph = $line;
}

( $line, $ref ) = $self->shiftline();
}
}

sub parse_list() {
my $self = shift;
my $line = shift;
my $ref = shift;

$line =~ m/^\* (.+)/ or return;
my $content = $1;

$self->pushline( "* " . $self->translate( $content, $ref, "list" ) . "\n" );

return 1;
}

sub parse_quote() {
my $self = shift;
my $line = shift;
my $ref = shift;

$line =~ m/^(> *)(.+)/ or return;
my $prefix = $1;
my $content = $2;

$self->pushline( $prefix . $self->translate( $content, $ref, "quote" ) . "\n" );

return 1;
}

sub parse_link() {
my $self = shift;
my $line = shift;
my $ref = shift;

$line =~ m/^(=>[ \t]+[^ \t]+)(?:([ \t]+)(.*))?/ or return;
my $prefix = $1;
my $separator = $2;
my $content = $3;

my $result = $prefix;
$result .= $separator . $self->translate( $content, $ref, "link" )
if $content;
$self->pushline( $result . "\n" );

return 1;
}

1;

=head1 STATUS OF THIS MODULE
Tested successfully on simple Gemtext files, such as the official Gemtext documentation.
=head1 SEE ALSO
L<Locale::Po4a::TransTractor(3pm)>, L<po4a(7)|po4a.7>
=head1 AUTHORS
gemmaro <gemmaro.dev@gmail.com>
=head1 COPYRIGHT AND LICENSE
Copyright © 2024 gemmaro <gemmaro.dev@gmail.com>.
This program is free software; you may redistribute it and/or modify it
under the terms of GPL v2.0 or later (see the COPYING file).
=cut
20 changes: 20 additions & 0 deletions t/fmt-gemtext.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Gemtext module tester.

#########################

use strict;
use warnings;

use lib q(t);
use Testhelper;

my @tests;

push @tests,
{
'format' => 'gemtext',
'input' => "fmt/gemtext/basic.gmi",
};

run_all_tests(@tests);
0;
21 changes: 21 additions & 0 deletions t/fmt/gemtext/basic.gmi
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
This is a normal text line.

=> gemini://example.org An example link

``` alt text
Here is a preformatted text.
```

Here are exactly two blank lines:


# Heading

## Sub Heading

### Sub sub heading

* Item 1
* Item 2

> This is a quote.
21 changes: 21 additions & 0 deletions t/fmt/gemtext/basic.norm
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
This is a normal text line.

=> gemini://example.org An example link

``` alt text
Here is a preformatted text.
```

Here are exactly two blank lines:


# Heading

## Sub Heading

### Sub sub heading

* Item 1
* Item 2

> This is a quote.
83 changes: 83 additions & 0 deletions t/fmt/gemtext/basic.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR Free Software Foundation, Inc.
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2024-02-07 22:02+0900\n"
"PO-Revision-Date: 2024-02-07 22:09+0900\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#. type: paragraph
#: basic.gmi:1
#, no-wrap
msgid "This is a normal text line."
msgstr "THIS IS A NORMAL TEXT LINE."

#. type: link
#: basic.gmi:3
#, no-wrap
msgid "An example link"
msgstr "AN EXAMPLE LINK"

#. type: alt text
#: basic.gmi:5
#, no-wrap
msgid "alt text"
msgstr "ALT TEXT"

#. type: preformatted text
#: basic.gmi:7
#, no-wrap
msgid "Here is a preformatted text."
msgstr "HERE IS A PREFORMATTED TEXT."

#. type: paragraph
#: basic.gmi:9
#, no-wrap
msgid "Here are exactly two blank lines:"
msgstr "HERE ARE EXACTLY TWO BLANK LINES:"

#. type: heading #
#: basic.gmi:12
#, no-wrap
msgid "Heading"
msgstr "HEADING"

#. type: heading ##
#: basic.gmi:14
#, no-wrap
msgid "Sub Heading"
msgstr "SUB HEADING"

#. type: heading ###
#: basic.gmi:16
#, no-wrap
msgid "Sub sub heading"
msgstr "SUB SUB HEADING"

#. type: list
#: basic.gmi:18
#, no-wrap
msgid "Item 1"
msgstr "ITEM 1"

#. type: list
#: basic.gmi:19
#, no-wrap
msgid "Item 2"
msgstr "ITEM 2"

#. type: quote
#: basic.gmi:21
#, no-wrap
msgid "This is a quote."
msgstr "THIS IS A QUOTE."
Loading

0 comments on commit c8294c3

Please sign in to comment.