Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#!/usr/bin/env perl
use strict;
use warnings;
use Pod::Usage;
use Text::Markdown 'markdown';
use HTML::TreeBuilder;
use List::Util 'max';
# デフォルトのリストスタイル
# disc: 黒丸
# square: 四角
# circle: 白丸
# alpha: アルファベット
use constant DEFAULT_LIST => 'disc';
# リストの文字数上限
# WEB+DB PRESSの場合、リストは、1行63桁(文字)まで
# 書籍の場合、リストは1行69桁(文字)まで
use constant MAX_LIST_LENGTH => 69;
# 本文埋め込みリストの文字数上限
# WEB+DB PRESSの場合、本文リストは1行55桁(文字)まで
# 書籍の場合、本文リストは1行73桁(文字)まで
use constant MAX_INLINE_LIST_LENGTH => 73;
sub to_inao {
my $text = shift;
my $html = markdown($text);
my $tree = HTML::TreeBuilder->new;
$tree->no_space_compacting(1);
$tree->parse_content(\$html);
my $inao = q[];
my $body = $tree->find('body');
for my $elem ($body->content_list) {
if ($elem->tag =~ /^h(\d+)/) {
my $level = $1;
$inao .= '' x $level;
$inao .= $elem->as_trimmed_text;
$inao .= "\n";
}
elsif ($elem->tag eq 'p') {
my $p = q[];
for my $inline ($elem->content_list) {
if (ref $inline eq '') {
# (注:)は脚注としてあつかう
$inline =~ s!\(注:(.+?)\)!◆注/◆$1◆/注◆!gs;
# 改行を取り除く
$inline =~ s/(\n|\r)//g;
# キャプション
$inline =~ s!^●(.+?)::(.+)!$1\t$2!;
$p .= $inline;
}
elsif ($inline->tag eq 'code') {
$p .= '◆cmd/◆';
$p .= $inline->as_trimmed_text;
$p .= '◆/cmd◆';
}
elsif ($inline->tag eq 'strong') {
$p .= '◆b/◆';
$p .= $inline->as_trimmed_text;
$p .= '◆/b◆';
}
elsif ($inline->tag eq 'em') {
$p .= '◆i/◆';
$p .= $inline->as_trimmed_text;
$p .= '◆/i◆';
}
elsif ($inline->tag eq 'kbd') {
$p .= $inline->as_trimmed_text;
$p .= '';
}
elsif ($inline->tag eq 'span') {
my $class = $inline->attr('class');
# 赤字
# <span class='red'>赤字</span>
if ($class eq 'red') {
$p .= '◆red/◆';
$p .= $inline->as_trimmed_text;
$p .= '◆/red◆';
}
# ruby
# <span class='ruby'>漢字(かんじ)</span>
elsif ($class eq 'ruby') {
my $ruby = $inline->as_trimmed_text;
$ruby =~ s!(.+)\((.+)\)!◆ルビ/◆$1$2◆/ルビ◆!;
$p .= $ruby;
}
# その他の記号
# <span class='symbol'>=></span>
elsif ($class eq 'symbol') {
$p .= '';
$p .= $inline->as_trimmed_text;
$p .= '';
}
}
}
if ($p !~ /^[\s ]+$/) {
$inao .= "$p\n";
}
}
elsif ($elem->tag eq 'pre') {
my $code = $elem->find('code');
my $text = '';
if (defined($code)) {
$text = $code->as_text;
}
my $list_label = 'list';
my $comment_label = 'comment';
# キャプション
$text =~ s!●(.+?)::(.+)!$1\t$2!s;
# 「!!! cmd」で始まるコードブロックはコマンドライン(黒背景)
if ($text =~ /!!!(\s+)?cmd/) {
$text =~ s/.+?\n//;
$list_label .= '-white';
$comment_label .= '-white';
}
# asciiのみカウント。日本語は目視でがんばる
my $max = max map { length } grep /^[\x00-\x7f]*$/, split /\r?\n/, $text;
if (defined($max)) {
if ($text =~ /^●/) {
if ($max > MAX_LIST_LENGTH) {
warn "リストは" . MAX_LIST_LENGTH . "文字まで!(現在$max使用):\n$text\n\n";
}
}
else {
if ($max > MAX_INLINE_LIST_LENGTH) {
warn "本文埋め込みリストは" . MAX_INLINE_LIST_LENGTH . "文字まで!(現在$max使用):\n$text\n\n";
}
}
} else {
warn 'リスト中の文字列に日本語が入っており、最大文字数を正しく計算できませんでした。 See: ' .$0. ':'. $= . "\n";
warn '-' x 72 . "\n";
warn $text;
warn '-' x 72 . "\n";
warn "\n";
}
# コード内コメント
$text =~ s!\(注:(.+?)\)!$comment_label/◆$1◆/$comment_label!gs;
# コード内強調
$text =~ s!\*\*(.+?)\*\*!◆cmd-b/◆$1◆/cmd-b◆!gs;
$inao .= "$list_label/◆\n";
$inao .= $text;
$inao .= "◆/$list_label\n";
}
elsif ($elem->tag eq 'ul') {
for my $list ($elem->find('li')) {
$inao .= '' . $list->as_trimmed_text . "\n";
}
}
elsif ($elem->tag eq 'ol') {
my $list_style = $elem->attr('class') || DEFAULT_LIST;
my $s = {
disc => '',
circle => '',
square => '',
alpha => '',
}->{$list_style};
my $i = $list_style eq 'alpha' ? 'a' : 1;
for my $list ($elem->find('li')) {
$inao .= $i++ . $s . $list->as_trimmed_text . "\n";
}
}
elsif ($elem->tag eq 'table') {
my $summary = $elem->attr('summary') || '';
$summary =~ s!(.+?)::(.+)!$1\t$2\n!;
$inao .= "◆table/◆\n";
$inao .= $summary;
$inao .= "◆table-title◆";
for my $table ($elem->find('tr')) {
for my $item ($table->find('th')){
$inao .= $item->as_trimmed_text;
$inao .= "\t";
}
for my $item ($table->find('td')){
$inao .= $item->as_trimmed_text;
$inao .= "\t";
}
chop($inao);
$inao .= "\n"
}
$inao .= "◆/table◆\n";
}
elsif ($elem->tag eq 'div' and $elem->attr('class') eq 'column') {
$inao .= "◆column/◆\n";
$inao .= to_inao($elem->as_text);
$inao .= "◆/column◆\n";
}
elsif ($elem->tag eq 'blockquote') {
my $blockquote = $elem->as_trimmed_text;
$blockquote =~ s/(\s)//g;
$inao .= "◆quote/◆\n";
$inao .= $blockquote;
$inao .= "\n◆/quote◆\n";
}
}
return $inao;
}
my $infile = $ARGV[0]
or pod2usage(-1);
open my $fh, '<', $infile or die $!;
my $text = do { local $/; <$fh> };
close $fh;
print to_inao($text);
__END__
=head1 NAME
markdown2inao.pl - markdown to inao converter
=head1 SYNOPSIS
markdown2inao.pl input.markdown.txt
=cut
# 見出し1
 段落冒頭の字下げは、このように手動でお願いします。
改行は自動で取り除かれます。
このように。
 _斜体(イタリック)_通常のところ**強調**通常のことろ`インラインのコード`通常のところ(注:注釈ですよ。)通常のところ<kbd>Enter</kbd>←キーボードになる?<span class='red'>これは赤文字</span>通常のところ<span class='ruby'>外村(ほかむら)</span>
> 引用です引用です引用です引用です引用です引用です引用です引用です
> 引用です引用です引用です引用です引用です引用です引用です引用です
> 引用です引用です引用です引用です引用です引用です引用です引用です
> 引用です引用です引用です引用です引用です引用です引用です引用です
<div class='column'>
#### コラム見出し
 本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文
##### コラム小見出し
 コラム内での**強調**なんかも可能?
</div>
## 見出し2
●リスト1.1::テストリスト1
* リスト1
* リスト2
* リスト3
* リスト4
* リスト5
●リスト1.2::テストリスト2
1. リスト1
2. リスト2
3. リスト3
4. リスト4
5. リスト5
●リスト1.3::テストリスト3
<ol class='circle'>
<li>リスト1</li>
<li>リスト2</li>
<li>リスト3</li>
<li>リスト4</li>
<li>リスト5</li>
</ol>
●リスト1.4::テストリスト4
<ol class='square'>
<li>リスト1</li>
<li>リスト2</li>
<li>リスト3</li>
<li>リスト4</li>
<li>リスト5</li>
</ol>
●リスト1.5::テストリスト5
<ol class='alpha'>
<li>リスト1</li>
<li>リスト2</li>
<li>リスト3</li>
<li>リスト4</li>
<li>リスト5</li>
</ol>
### 見出し3
本文埋め込みブロックの例
function **foo**(a) { // コード内強調
alert(a); (注:こんな風にコメントがつけられます)
}
名前つきのコードブロックの例
●コード1.1::テストコード1
(注:見出し的にも使えます)
function bar(b) {
alert(b);
}
コマンドラインのコードブロック
!!! cmd
●コード1.2::テストコード2
(注:見出し的にも使えます)
function bar(b) {
alert(b);
}
●画像1.1::テスト画像1
figure/sample.png
<table summary='表2::テストの表です'>
<tr>
<th>表タイトル1</th>
<th>表タイトル2</th>
</tr>
<tr>
<td>内容1</td>
<td>内容2</td>
</tr>
<tr>
<td>内容1</td>
<td>内容2</td>
</tr>
</table>
### キーボード
<kbd>A</kbd>~<kbd>Z</kbd>
<kbd>a</kbd>~<kbd>z</kbd>
<kbd>0</kbd>~<kbd>9</kbd>
<kbd>End</kbd>
<kbd>Alt</kbd>
<kbd>Ctrl</kbd>
<kbd>Control</kbd>
<kbd>Shift</kbd>
<kbd>Tab</kbd>
<kbd>Esc</kbd>
<kbd>Delete</kbd>
<kbd>Insert</kbd>
<kbd>Pause</kbd>
<kbd>Break</kbd>
<kbd>Home</kbd>
<kbd>Back Space</kbd>
<kbd>Enter</kbd>
<kbd>F10</kbd>
<kbd>F11</kbd>
<kbd>F12</kbd>
<kbd>F1</kbd>
<kbd>F2</kbd>
<kbd>F3</kbd>
<kbd>F4</kbd>
<kbd>F5</kbd>
<kbd>F6</kbd>
<kbd>F7</kbd>
<kbd>F8</kbd>
<kbd>F9</kbd>
<kbd>→</kbd>
<kbd>↓</kbd>
<kbd>↑</kbd>
<kbd>←</kbd>
<kbd>!</kbd>
<kbd>#</kbd>
<kbd>$</kbd>
<kbd>%</kbd>
<kbd>&</kbd>
<kbd>'</kbd>
<kbd>(</kbd>
<kbd>)</kbd>
<kbd>=</kbd>
<kbd>-</kbd>
<kbd>^</kbd>
<kbd>~</kbd>
<kbd>|</kbd>
<kbd>[</kbd>
<kbd>]</kbd>
<kbd>+</kbd>
<kbd>*</kbd>
<kbd>;</kbd>
<kbd>:</kbd>
<kbd>,</kbd>
<kbd>.</kbd>
<kbd>/</kbd>
<kbd>?</kbd>
<kbd>_</kbd>
<kbd>@</kbd>
<kbd>`</kbd>
<kbd>"</kbd>
### そのほか記号
<span class='symbol'>→</span>
<span class='symbol'>←</span>
<span class='symbol'>↑</span>
<span class='symbol'>↓</span>
<span class='symbol'>←→</span>
<span class='symbol'>>=</span>
<span class='symbol'>=></span>
■見出し1
 段落冒頭の字下げは、このように手動でお願いします。改行は自動で取り除かれます。このように。
 ◆i/◆斜体(イタリック)◆/i◆通常のところ◆b/◆強調◆/b◆通常のことろ◆cmd/◆インラインのコード◆/cmd◆通常のところ◆注/◆注釈ですよ。◆/注◆通常のところEnter▲←キーボードになる?◆red/◆これは赤文字◆/red◆通常のところ◆ルビ/◆外村◆ほかむら◆/ルビ◆
◆quote/◆
引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です引用です
◆/quote◆
◆column/◆
■■■■コラム見出し
 本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文
■■■■■コラム小見出し
 コラム内での◆b/◆強調◆/b◆なんかも可能?
◆/column◆
■■見出し2
●リスト1.1 テストリスト1
・リスト1
・リスト2
・リスト3
・リスト4
・リスト5
●リスト1.2 テストリスト2
1●リスト1
2●リスト2
3●リスト3
4●リスト4
5●リスト5
●リスト1.3 テストリスト3
1○リスト1
2○リスト2
3○リスト3
4○リスト4
5○リスト5
●リスト1.4 テストリスト4
1■リスト1
2■リスト2
3■リスト3
4■リスト4
5■リスト5
●リスト1.5 テストリスト5
a●リスト1
b●リスト2
c●リスト3
d●リスト4
e●リスト5
■■■見出し3
本文埋め込みブロックの例
◆list/◆
function ◆cmd-b/◆foo◆/cmd-b◆(a) { // コード内強調
alert(a); ◆comment/◆こんな風にコメントがつけられます◆/comment◆
}
◆/list◆
名前つきのコードブロックの例
◆list/◆
●コード1.1 テストコード1
◆comment/◆見出し的にも使えます◆/comment◆
function bar(b) {
alert(b);
}
◆/list◆
コマンドラインのコードブロック
◆list-white/◆
●コード1.2 テストコード2
◆comment-white/◆見出し的にも使えます◆/comment-white◆
function bar(b) {
alert(b);
}
◆/list-white◆
●画像1.1 テスト画像1
figure/sample.png
◆table/◆
●表2 テストの表です
◆table-title◆表タイトル1 表タイトル2
内容1 内容2
内容1 内容2
◆/table◆
■■■キーボード
A▲~Z▲
a▲~z▲
0▲~9▲
End▲
Alt▲
Ctrl▲
Control▲
Shift▲
Tab▲
Esc▲
Delete▲
Insert▲
Pause▲
Break▲
Home▲
Back Space▲
Enter▲
F10▲
F11▲
F12▲
F1▲
F2▲
F3▲
F4▲
F5▲
F6▲
F7▲
F8▲
F9▲
→▲
↓▲
↑▲
←▲
!▲
#▲
$▲
%▲
&▲
'▲
(▲
)▲
=▲
-▲
^▲
~▲
|▲
[▲
]▲
+▲
*▲
;▲
:▲
,▲
.▲
/▲
?▲
_▲
@▲
`▲
"▲
■■■そのほか記号
◆→◆
◆←◆
◆↑◆
◆↓◆
◆←→◆
◆>=◆
◆=>◆
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment