my $parser = SVG::Parser->new;
@images = map {[ $sub->($_) => $parser->parse_file($_) ]} @images;
my ($x, $mh) = (0, 0);
+ my %ids = map { $_->[0] => 1 } @images; # start with image names
for (@images) {
my ($img, $doc) = @$_;
$svg->attr(version => undef);
my $view = $sprite->view(id => $img, viewBox => "$x 0 $w $h");
$x += $w + 5;
+
+ my @all_elems = $svg->getElements;
+ my @duplicate_ids;
+ for my $elem (@all_elems) {
+ my $id = $elem->attr('id');
+ next unless $id;
+ if ($ids{$id}) {
+ push @duplicate_ids, $id;
+ } else {
+ $ids{$id} = 1;
+ }
+ }
+
+ warn <<"EOF" if @duplicate_ids && !$ENV{SVG_SPRITEMAKER_NO_DUPLICATE_WARNINGS};
+Some IDs (@duplicate_ids) in $img also exist in previous images.
+Trying to fix automatically, but this might produce a broken SVG.
+Fix IDs manually to avoid incorrect output.
+EOF
+
+ for my $oid (@duplicate_ids) {
+ my $nid = $oid;
+ $nid .= '_' while $ids{$nid};
+ $svg->getElementByID($oid)->attr(id => $nid);
+ for my $elem (@all_elems) {
+ my %attribs = %{$elem->getAttributes};
+ for my $key (keys %attribs) {
+ if ($attribs{$key} =~ /#$oid\b/) {
+ $attribs{$key} =~ s/#$oid\b/#$nid/g;
+ $elem->attr($key => $attribs{$key});
+ }
+ }
+ if ($elem->cdata =~ /#$oid\b/) {
+ $elem->cdata($elem->cdata =~ s/#$oid\b/#$nid/gr);
+ }
+ }
+ }
+
$view->getParent->insertAfter($svg, $view);
}
where I<$prefix> is the value of the first argument.
+If an ID is shared between two or more input files, this module will
+try to rename each occurence except for the first one. This operation
+might have false positives (attributes/cdatas that are mistakenly
+identified to contain the ID-to-be-renamed) and false negatives
+(attributes/cdatas that actually contain the ID-to-be-renamed but this
+is missed by the module), and as such SVG::SpriteMaker will warn if
+duplicate IDs are detected. You can suppress this warning by setting
+the C<SVG_SPRITEMAKER_NO_DUPLICATE_WARNINGS> environment variable to a
+true value.
+
=head1 SEE ALSO
L<svg-spritemaker>, L<https://css-tricks.com/svg-fragment-identifiers-work/>
=back
+If an ID is shared between two or more input files, this program will
+try to rename each occurence except for the first one. This operation
+might have false positives (attributes/cdatas that are mistakenly
+identified to contain the ID-to-be-renamed) and false negatives
+(attributes/cdatas that actually contain the ID-to-be-renamed but this
+is missed by the module), and as such svg-spritemaker will warn if
+duplicate IDs are detected. You can suppress this warning by setting
+the C<SVG_SPRITEMAKER_NO_DUPLICATE_WARNINGS> environment variable to a
+true value.
+
=head1 SEE ALSO
L<SVG::SpriteMaker>, L<https://css-tricks.com/svg-fragment-identifiers-work/>
use strict;
use warnings;
-use Test::More tests => 3;
+use Test::More tests => 5;
BEGIN { use_ok('SVG::SpriteMaker') };
+# Don't warn, we intentionally have a duplicate ID
+local $ENV{SVG_SPRITEMAKER_NO_DUPLICATE_WARNINGS} = 1;
my $sprite = make_sprite frag => <t/*.svg>;
my @elements = $sprite->getFirstChild->getChildren;
ok $sprite->getElementByID('frag-rect'), 'sprite contains #frag-rect';
ok $sprite->getElementByID('frag-circle'), 'sprite contains #frag-circle';
+like $sprite->xmlify, qr/id="thing"/, 'sprite contains #thing';
+like $sprite->xmlify, qr/id="thing_"/, 'sprite contains #thing_';