+ return @html;
+}
+
+sub tabletag {
+ my ($self) = @_;
+ my $class = 'glyphs';
+ $class .= ' dilabel' if @{ $self->{anno} };
+ return sprintf '<table class="%s">', $class;
+}
+
+sub table {
+ my ($self, $digraphs) = @_;
+
+ my @rows;
+
+ my @colheads;
+ while ($digraphs->[0] !~ /^\./) {
+ my $cell = shift @$digraphs or last;
+ if ($cell eq '>') {
+ push @colheads, '<tr>';
+ next;
+ }
+ push @colheads, join('',
+ '<',
+ $cell =~ s/^-// ? 'td' : 'th',
+ $cell =~ s/:(.*)// && qq{ title="$1"},
+ $cell =~ s/^(>+)// && ' colspan='.(length($1) + 1),
+ '>',
+ $cell eq '_' ? ' ' : $cell
+ );
+ }
+ push @rows, sprintf '<thead><tr>%s<tbody>', join '', @colheads if @colheads;
+ push @rows, $self->row($digraphs);
+
+ return join '', map {"$_\n"} $self->tabletag, @rows, '</table>';
+}
+
+sub print {
+ my $self = shift;
+ while (@_) {
+ print '<div class="section">';
+ printf '<h2>%s</h2>', shift unless ref $_[0];
+ print "\n\n";
+ while (ref $_[0] and $_ = shift) {
+ print $self->table($_);
+ }
+ print "\n</div>";
+ }
+}
+
+sub legend {
+ my $self = shift;
+ my @classes = $self->{style} eq 'univer' ? (
+ [l5 => 'unicode 1.1'],
+ [l4 => '20th century'],
+ [l3 => 'in 6.0 (2010)'],
+ [l2 => 'recent assignments'],
+ [l1 => 'proposed'],
+ [ex => 'irregular'],
+ ) : (
+ [l5 => 'ascii'],
+ [l4 => $self->{style} eq 'di' ? 'digraph' : 'latin1'],
+ [l3 => $self->{style} eq 'di' ? 'proposed' : 'HTML4'],
+ [l2 => 'unicode ≤6.0'],
+ [l1 => 'other unicode'],
+ [ex => 'discouraged'],
+ );
+
+ return (
+ '<div class="legend"><table class="glyphs"><tr>',
+ (map { sprintf '<td class="X %s">%s', @{$_} } @classes),
+ '</table></div>',
+ );