package SWE::Lang::XML2HTML;
use strict;
our $ConverterVersion = 2;
sub AA_NS () { q }
sub HTML_NS () { q }
sub SW09_NS () { q }
sub SW10_NS () { q }
sub XML_NS () { q }
my $templates = {};
$templates->{''}->{''} = sub {
my ($items, $item) = @_;
if ($item->{node}->node_type == $item->{node}->ELEMENT_NODE) {
unshift @$items,
map {{%$item, node => $_, parent => $item->{parent}}}
@{$item->{node}->child_nodes};
} else {
$item->{parent}->manakai_append_text ($item->{node}->node_value);
}
};
$templates->{(HTML_NS)}->{head} = sub { };
$templates->{(HTML_NS)}->{section} = sub {
my ($items, $item) = @_;
my $section_el = $item->{doc}->create_element_ns (HTML_NS, 'div');
$section_el->set_attribute (class => 'section sw-section');
$item->{parent}->append_child ($section_el);
unshift @$items,
map {{%$item, node => $_, parent => $section_el,
heading_level => $item->{heading_level} + 1}}
@{$item->{node}->child_nodes};
};
$templates->{(HTML_NS)}->{h1} = sub {
my ($items, $item) = @_;
my $h_el = $item->{doc}->create_element_ns
(HTML_NS,
'h' . ($item->{heading_level} > 6 ? '6' : $item->{heading_level}));
$item->{parent}->append_child ($h_el);
unshift @$items,
map {{%$item, node => $_, parent => $h_el}}
@{$item->{node}->child_nodes};
};
$templates->{(HTML_NS)}->{p} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns
(HTML_NS, $item->{node}->manakai_local_name);
$item->{parent}->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$el->set_attribute (class => $class) if defined $class;
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
my $colspan = $item->{node}->get_attribute ('colspan');
$el->set_attribute (colspan => $colspan) if defined $colspan;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(HTML_NS)}->{$_} = $templates->{(HTML_NS)}->{p}
for qw/
ul ol dl li dt dd table tbody tr td blockquote pre
abbr cite code dfn kbd ruby samp span sub sup time var em strong
/;
$templates->{(HTML_NS)}->{rt} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'rp');
$el->text_content (' (');
$item->{parent}->append_child ($el);
$el = $item->{doc}->create_element_ns
(HTML_NS, $item->{node}->manakai_local_name);
$item->{parent}->append_child ($el);
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
$el = $item->{doc}->create_element_ns (HTML_NS, 'rp');
$el->text_content (') ');
$item->{parent}->append_child ($el);
};
$templates->{(SW09_NS)}->{insert} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'ins');
$item->{parent}->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$el->set_attribute (class => $class) if defined $class;
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW09_NS)}->{delete} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'del');
$item->{parent}->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$el->set_attribute (class => $class) if defined $class;
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW10_NS)}->{'comment-p'} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'div');
$item->{parent}->append_child ($el);
$el->set_attribute (class => 'sw-comment-p');
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW10_NS)}->{ed} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'div');
$item->{parent}->append_child ($el);
$el->set_attribute (class => 'sw-ed');
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(AA_NS)}->{aa} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'span');
$item->{parent}->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$class //= '';
$class .= ' sw-aa';
$el->set_attribute (class => $class);
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW10_NS)}->{csection} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'cite');
$item->{parent}->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$class //= '';
$class .= ' sw-csection';
$el->set_attribute (class => $class);
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW10_NS)}->{key} = sub {
my ($items, $item) = @_;
my $el0 = $item->{doc}->create_element_ns (HTML_NS, 'kbd');
$item->{parent}->append_child ($el0);
my $el = $item->{doc}->create_element_ns (HTML_NS, 'kbd');
$el0->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$el->set_attribute (class => $class) if defined $class;
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW10_NS)}->{qn} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'code');
$item->{parent}->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$class //= '';
$class .= ' sw-qn';
$el->set_attribute (class => $class);
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW10_NS)}->{src} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'cite');
$item->{parent}->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$class //= '';
$class .= ' sw-src';
$el->set_attribute (class => $class);
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW09_NS)}->{weak} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'small');
$item->{parent}->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$class //= '';
$class .= ' sw-weak';
$el->set_attribute (class => $class);
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW10_NS)}->{title} = sub {
my ($items, $item) = @_;
unless ($item->{parent}->has_attribute ('title')) {
$item->{parent}->set_attribute (title => $item->{node}->text_content);
}
};
$templates->{(SW10_NS)}->{nsuri} = sub {
my ($items, $item) = @_;
unless ($item->{parent}->has_attribute ('title')) {
$item->{parent}->set_attribute
(title => '<' . $item->{node}->text_content . '>');
}
};
$templates->{(HTML_NS)}->{q} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns
(HTML_NS, $item->{node}->manakai_local_name);
$item->{parent}->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$el->set_attribute (class => $class) if defined $class;
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
if ($item->{node}->has_attribute_ns (SW09_NS, 'resScheme')) {
## TODO: ...
}
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(HTML_NS)}->{del} = $templates->{(HTML_NS)}->{q};
$templates->{(HTML_NS)}->{ins} = $templates->{(HTML_NS)}->{q};
$templates->{(SW09_NS)}->{rubyb} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'ruby');
$item->{parent}->append_child ($el);
my $class = $item->{node}->get_attribute ('class');
$class //= '';
$class .= ' sw-rubyb';
$el->set_attribute (class => $class);
my $lang = $item->{node}->get_attribute_ns (XML_NS, 'lang');
$el->set_attribute (lang => $lang) if defined $lang;
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW09_NS)}->{anchor} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'a');
$item->{parent}->append_child ($el);
$el->set_attribute (class => 'sw-anchor');
my $name = $item->{node}->text_content;
if ($name eq '//') {
$name = 'HomePage'; ## Don't use $homepage_name - this is not configurable
} elsif ($name =~ s!^\.//!!) {
$name = $item->{name} . '//' . $name;
} elsif ($name =~ s!^\.\.//!!) {
my $pname = $item->{name};
$pname =~ s/(?:(?!//).)+$><>;
$name = $pname . '//' . $name;
}
$name =~ s/\s+/ /g;
$name =~ s/^ //;
$name =~ s/ $//;
$name = 'HomePage' unless length $name;
my $url = $item->{name_to_url}->($name, $item->{name});
my $anchor = $item->{node}->get_attribute_ns (SW09_NS, 'anchor');
if (defined $anchor) {
$url .= '#anchor-' . $anchor;
my $t = $item->{doc}->create_text_node (' (>>' . $anchor . ')');
unshift @$items, {%$item, node => $t, parent => $el};
}
$el->set_attribute (href => $url);
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW09_NS)}->{'anchor-internal'} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'a');
$item->{parent}->append_child ($el);
$el->set_attribute (class => 'sw-anchor-internal');
my $id = $item->{node}->get_attribute_ns (SW09_NS, 'anchor') + 0;
$el->set_attribute (href => '#anchor-' . $id);
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW09_NS)}->{'anchor-end'} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'a');
$item->{parent}->append_child ($el);
$el->set_attribute (class => 'sw-anchor-end');
my $id = $item->{node}->get_attribute_ns (SW09_NS, 'anchor') + 0;
$el->set_attribute (id => 'anchor-' . $id);
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW09_NS)}->{'anchor-external'} = sub {
my ($items, $item) = @_;
$item->{parent}->manakai_append_text ('<');
my $el = $item->{doc}->create_element_ns (HTML_NS, 'a');
$item->{parent}->append_child ($el);
$el->set_attribute (class => 'sw-anchor-external');
$item->{parent}->manakai_append_text ('>');
my $scheme = $item->{node}->get_attribute_ns (SW09_NS, 'resScheme');
if ($scheme eq 'URI' or $scheme eq 'URL') {
$el->set_attribute
(href => $item->{node}->get_attribute_ns (SW09_NS, 'resParameter'));
} else {
## TODO: ...
}
unshift @$items,
map {{%$item, node => $_, parent => $el}}
@{$item->{node}->child_nodes};
};
$templates->{(SW09_NS)}->{image} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'div');
$el->set_attribute (class => 'article sw-image');
$item->{parent}->append_child ($el);
my $type;
my $alt;
my $head_el = $item->{node}->owner_document->manakai_head;
if ($head_el) {
for (@{$head_el->child_nodes}) {
next if $_->node_type != $_->ELEMENT_NODE;
next if ($_->namespace_uri // '') ne SW09_NS;
next if $_->manakai_local_name ne 'parameter';
my $name = $_->get_attribute ('name');
if ($name eq 'image-type' or $name eq 'image-alt') {
for (@{$_->child_nodes}) {
next if $_->node_type != $_->ELEMENT_NODE;
next if ($_->namespace_uri // '') ne SW09_NS;
next if $_->manakai_local_name ne 'value';
if ($name eq 'image-type') {
$type //= $_->text_content;
} elsif ($name eq 'image-alt') {
$alt //= $_->text_content;
}
last;
}
last if defined $type and defined $alt;
}
}
}
$type //= 'application/octet-stream';
$type =~ tr{a-zA-Z0-9.+-_/-}{}cd;
## NOTE: '!', '#', '$', '&', '^' are also allowed according to RFC 4288.
my $data = $item->{node}->text_content;
$data =~ s/\s+//g;
my $img_el = $item->{doc}->create_element_ns (HTML_NS, 'img');
$img_el->set_attribute (alt => $alt // '');
$img_el->set_attribute (src => 'data:' . $type . ';base64,' . $data);
$el->append_child ($img_el);
};
$templates->{(SW09_NS)}->{replace} = sub {
my ($items, $item) = @_;
my $el = $item->{doc}->create_element_ns (HTML_NS, 'span');
$el->set_attribute (class => 'sw-replace');
$el->text_content ($item->{node}->get_attribute ('by') // '');
$item->{parent}->append_child ($el);
};
sub convert ($$$$$$) {
shift;
my $name = shift;
my $swml = shift;
my $doc = shift;
my $name_to_url = shift;
my $heading_level = shift;
my $df = $doc->create_document_fragment;
my @items = map {{doc => $doc,
name_to_url => $name_to_url,
heading_level => $heading_level, name => $name,
node => $_, parent => $df}} @{$swml->child_nodes};
while (@items) {
my $item = shift @items;
my $nsuri = $item->{node}->namespace_uri // '';
my $ln = $item->{node}->manakai_local_name // '';
my $template = $templates->{$nsuri}->{$ln} || $templates->{''}->{''};
$template->(\@items, $item);
}
return $df;
} # convert_swml_to_html
1;