use
5.020;
our
%RULES
= (
tableCell
=> {
filter
=> [
'th'
,
'td'
],
replacement
=>
sub
(
$content
,
$node
,
$options
,
$context
) {
return
cell(
$content
,
$node
);
},
},
tableRow
=> {
filter
=>
'tr'
,
replacement
=>
sub
(
$content
,
$node
,
$options
,
$context
) {
my
$borderCells
=
''
;
my
$alignMap
= {
left
=>
':--'
,
right
=>
'--:'
,
center
=>
':-:'
};
if
(
$content
=~ m!\A\|( \|)+\z! ) {
return
''
;
}
if
(isHeadingRow(
$node
)) {
my
@ch
=
$node
->childNodes;
for
my
$ch
(
$node
->childNodes) {
my
$border
=
'---'
;
my
$align
=
lc
(
$ch
->getAttribute(
'align'
) ||
''
);
if
(
$align
) {
$border
=
$alignMap
->{
$align
} ||
$border
;
}
$borderCells
.= cell(
$border
,
$ch
,
undef
)
}
}
return
"\n"
.
$content
. (
$borderCells
?
"\n"
.
$borderCells
:
''
)
}
},
table
=> {
filter
=>
sub
(
$rule
,
$node
,
$options
) {
my
$firstRow
=
$node
->find(
'.//td/..'
,
$node
)->
shift
;
return
uc
$node
->nodeName eq
'TABLE'
&&
$firstRow
&& isHeadingRow(
$firstRow
)
},
replacement
=>
sub
(
$content
,
$node
,
$options
,
$context
) {
$content
=~ s/\n\n/\n/;
return
"\n\n"
.
$content
.
"\n\n"
}
},
tableSection
=> {
filter
=> [
'thead'
,
'tbody'
,
'tfoot'
],
replacement
=>
sub
(
$content
,
$node
,
$options
,
$context
) {
return
$content
}
}
);
sub
isHeadingRow (
$tr
) {
return
if
!
$tr
;
my
$parentNode
=
$tr
->parentNode;
my
$n
=
$tr
->can(
'_node'
) ?
$tr
->_node :
$tr
;
return
(
uc
(
$parentNode
->nodeName) eq
'THEAD'
||
(
$n
->isEqual(
$parentNode
->firstChild)
&& (
uc
$parentNode
->nodeName eq
'TABLE'
|| isFirstTbody(
$parentNode
))
&& all {
uc
(
$_
->nodeName) eq
'TH'
}
$tr
->childNodes
)
)
}
sub
isFirstTbody (
$element
) {
my
$previousSibling
=
$element
->previousSibling;
return
(
uc
$element
->nodeName eq
'TBODY'
&& (
!
$previousSibling
||
(
uc
$previousSibling
->nodeName eq
'THEAD'
&&
$previousSibling
->textContent =~ /^\s*$/
)
)
)
}
sub
cell (
$content
,
$node
,
$escape
=1) {
my
$first
= !
$node
->previousSibling;
my
$prefix
=
' '
;
if
(
$first
) {
$prefix
=
'| '
};
if
(
$escape
) {
$content
= Text::HTML::Turndown->escape(
$content
);
}
$content
=~ s!\r?\n!<br/>!g;
return
$prefix
.
$content
.
' |'
}
sub
install (
$class
,
$target
) {
$target
->preprocess(
sub
(
$tree
) {
for
my
$table
(
$tree
->find(
'//table'
)->@*) {
if
(
$table
->find(
'./thead/td'
)->@* ) {
my
$head
=
$table
->find(
'./thead'
,
$table
)->
shift
;
my
$tr
=
$head
->ownerDocument->createElement(
'tr'
);
$tr
->appendChild(
$_
)
for
$head
->childNodes;
$head
->appendChild(
$tr
);
}
}
return
$tree
;
});
$target
->keep(
sub
(
$node
) {
my
$firstRow
=
$node
->find(
'.//tr'
)->
shift
;
return
uc
$node
->nodeName eq
'TABLE'
&& !isHeadingRow(
$firstRow
)
});
for
my
$key
(
keys
%RULES
) {
$target
->addRule(
$key
,
$RULES
{
$key
})
}
}
1;