Skip to content

Instantly share code, notes, and snippets.

@cognominal
Created October 21, 2009 05:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cognominal/214902 to your computer and use it in GitHub Desktop.
Save cognominal/214902 to your computer and use it in GitHub Desktop.
use v6;
# Null PMC access in type()
# in Main (file src/gen_setting.pm, line 295)
class SVG {
our subset Attr of Pair where { $_.value !~~ Array };
our subset Element of Pair where { $_.value ~~ Array };
our subset Text_node of Str;
our subset Node where Text_node | Element;
method serialize(Element $tree) {
visit($tree.list);
}
sub element(Str $name, @attrs, Node @children) {
@children
?? element_open($name, @attrs)
~ visit(@children)
~ element_close($name)
!! element_empty($name, @attrs);
}
sub element_open(Str $name, Attr @attrs) {
sprintf '<%s%s>', $name, element_attrs(@attrs);
}
sub element_close(Str $name) {
"</$name>";
}
sub element_empty(Str $name, Attr @attrs) {
sprintf '<%s%s />', $name, element_attrs(@attrs);
}
sub element_attrs(Attr @attrs) {
[~] @attrs.map({ sprintf ' %s="%s"', .key, escape(.value) });
}
sub escape(Str $str) {
my %charmap =
'>' => '&gt;',
'<' => '&lt;',
'"' => '&quot;',
'&' => '&amp;',
;
$str.subst( rx{ <[<>&"]> }, { %charmap{$_} }, :g);
}
sub visit(@list) {
[~] @list.map: -> $node {
if $node ~~ Str {
escape($node);
}
else {
my ($name, $subtree) = $node.kv;
my @attrs = grep Attr, $subtree.list;
my @children = grep Node, $subtree.list;
element($name, @attrs, @children);
}
}
}
}
=begin pod
=head1 NAME
SVG - Scalable Vector Graphics generation and handling
=head1 SYNOPSIS
=begin code
use v6;
use SVG;
my $svg = :svg[
:width(200), :height(200),
circle => [
:cx(100), :cy(100), :r(50)
],
text => [
:x(10), :y(20), "hello"
]
];
say SVG.serialize($svg);
=end code
=head1 DESCRIPTION
SVG is a Perl 6 class which outputs SVG from a nested data structure describing
the DOM representation of an SVG (Scalable Vector Graphics) image.
=head1 METHODS
=head2 serialize($hierarchy)
=head1 TESTING
The testing plan of SVG::Tiny seems alluring. Haven't looked closer at it,
though.
=head1 TODO
Add some kind of validation. Three competing ideas are given here: validate
at runtime, by calling a separate method in SVG; validate while serializing;
validate statically with a script that can understand Perl 6, and draw some
conclusions about the input to the .serialize method.
=head1 BUGS
Likely several. If any of them bites you, please get in touch and I'll see
what I can do.
=head1 SEE ALSO
L<http://www.w3.org/TR/SVG/>
=head1 AUTHORS
Carl Mäsak (masak on CPAN github #perl6, cmasak on gmail.com)
significant contributions made by Daniel Schröer.
=end pod
# vim: ft=perl6 sw=4 ts=4 expandtab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment