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;