The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Text::Xatena - Text-to-HTML converter with Xatena syntax.

SYNOPSIS

use Text::Xatena;

my $thx = Text::Xatena->new;
$thx->format($string);

# with some aggressive functions
$thx->format($string,
    inline => Text::Xatena::Inline::Aggressive->new(cache => Cache::MemoryCache->new)
);

Customizing inline formatting rule

Text::Xatena->new->format($string,
    inline => MyInline->new
);

package MyInline;
use strict;
use warnings;
use Text::Xatena::Inline::Base -Base;

match qr{\@([a-z0-9]+)} => sub {
    my ($self, $twitter_id) = @_;
    sprintf('<a href="http://twitter.com/%s">@%s</a>',
        $twitter_id,
        $twitter_id,
    );
};

1;

DESCRIPTION

Text::Xatena is a text-to-html converter.

Text::Xatena is comfortably to writing usual diary and blog, especially for programmers, writers treating long text.

What is Xatena

Xatena syntax is similar to Hatena syntax (implemented as Text::Hatena), but is independent from Hatena services and has more expandability.

Most block level syntax notations are supported and more compatibility with Hatena::Diary than Text::Hatena 0.20.

And don't support rare syntax or what isn't to be done of syntax formatter. (for example, linking keywords)

SYNTAX

Basically, Xatena convert single line breaks to <br/> and double line breaks to <p> element except "Stop P" syntax.

fooo
bar

baz

is converted to following:

<p>fooo<br/>bar</p>
<p>baz</p>

Blockquote

>>
quoted text

foobar
<<

is converted to following:

<blockquote>
<p>quoted text</p>
<p>foobar</p>
</blockquote>

with cite

>http://example.com/>
foobar
<<

is converted to following:

<blockquote cite="http://example.com/">
  <p>quote</p>
  <cite><a href="http://example.com/">http://example.com/</a></cite>
</blockquote>

Pre

>|
pre <a href="">formatted</a>
|<

is converted to following:

<pre>
pre <a href="">formatted</a>
</pre>

Super pre

>||
super pre <a>
||<

is converted to following:

<pre>
super pre &lt;a&gt;
</pre>

with lang

>|perl|
use Text::Xatena;
||<

is converted to following:

<pre class="code lang-perl">
use Text::Xatena;
</pre>

Stop P

Stop insert p or br.

><blockquote>
<p>
hogehoge br
</p>
</blockquote>< 

is converted to following:

<blockquote>
<p>
hogehoge br
</p>
</blockquote><

with custom block level element

><ins><
foobar
></ins><

is convert with auto inserting p to

<ins>
<p>foobar</p>
</ins>

Section

Create structured sections by * following heading.

* head1

foobar

** head2

*** head3

is converted to following:

<div class="section">
<h3>head1</h3>
<p>foobar</p>
  <div class="section">
  <h4>head2</h4>
    <div class="section">
    <h5>head3</h5>
    </div>
  </div>
</div>

List

unordered list

- ul
- ul
-- ul
-- ul
--- ul
- ul

is converted to following:

<ul>
  <li>ul</li>
  <li>ul</li>
  <li>
    <ul>
      <li>ul</li>
      <li>ul</li>
      <li>
        <ul>
          <li>ul</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>ul</li>
</ul>

ordered list

+ ol
+ ol
++ ol
++ ol
+++ ol
+ ol

is converted to following:

<ol>
  <li>ol</li>
  <li>ol</li>
  <li>
    <ol>
      <li>ol</li>
      <li>ol</li>
      <li>
        <ol>
          <li>ol</li>
        </ol>
      </li>
    </ol>
  </li>
  <li>ol</li>
</ol>

mixed list

- ul
- ul
-+ ol
-+ ol
-+ ol
- ul

definition list

:definition:description
:definition:description

is converted to following:

<dl>
  <dt>definition</dt>
  <dd>description</dd>
  <dt>definition</dt>
  <dd>description</dd>
</dl>

multiline

This is incompatible syntax with Hatena::Diary

:definition:
:: description
:definition:
:: description

Table

|*foo|*bar|*baz|
|test|test|test|
|test|test|test|

is converted to following:

<table>
  <tr>
    <th>foo</th>
    <th>bar</th>
    <th>baz</th>
  </tr>
  <tr>
    <td>test</td>
    <td>test</td>
    <td>test</td>
  </tr>
  <tr>
    <td>test</td>
    <td>test</td>
    <td>test</td>
  </tr>
</table>

Inline syntax

http://example.com/
ftp://example.com/
mailto:cho45@lowreal.net
[http://example.com/]

# using Xatena::Inline::Aggressive
[http://example.com/]
[http://example.com/:title] # auto retrieving from url
[http://example.com/:title=Foobar]
[http://example.com/:barcode] # show qrcode with google chart API
Deter inline syntax
[]http://example.com/[]
Footnote syntax
Perl((most famous light weight language))

is converted to

Perl<a href="#fn1">*1</a>

and footnote object is available in inline object, so you will do expand it like following:

my $thx = Text::Xatena->new;
my $inline = Text::Xatena::Inline->new;
my $formatted = $thx->format('aaa((foobar)) bbb((barbaz))', inline => $inline);
my $out = '';
$out .= '<div class="body">';
$out .= $formatted;
$out .= '</div>';
$out .= '<div class="notes">';
for my $footnote (@{ $inline->footnotes }) {
   $out .= sprintf('<div class="footnote" id="#fn%d">*%d: %s</div>',
     $footnote->{number},
     $footnote->{number},
     $footnote->{note},
   );
}
$out .= '</div>';

Compatibility with Hatena::Diary syntax

Some default behaviors of Xatena syntax are different from Hatena::Diary syntax.

Big differences:

1. Hatena::Diary syntax converts single break to <p> block but Xatena converts it to <br/>.
2. Hatena::Diary syntax converts * (heading notation) to simple <hn> element but Xatena converts it to <div class="section">
3. Xatena support multiline definition list

But Xatena supports Hatena::Diary compatible mode, you can change the behavior with a option.

my $thx = Text::Xatena->new(hatena_compatible => 1);

AUTHOR

cho45 <cho45@lowreal.net>

SEE ALSO

Text::Hatena

http://hatenadiary.g.hatena.ne.jp/keyword/%E3%81%AF%E3%81%A6%E3%81%AA%E8%A8%98%E6%B3%95%E4%B8%80%E8%A6%A7>

LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.