From: Marius Gavrilescu Date: Fri, 24 Feb 2017 00:27:47 +0000 (+0000) Subject: Try to fix duplicate IDs X-Git-Tag: 0.002~2 X-Git-Url: http://git.ieval.ro/?p=svg-spritemaker.git;a=commitdiff_plain;h=014f8c27d1123b5d338e675dcf5d06b4b269ba03 Try to fix duplicate IDs --- diff --git a/lib/SVG/SpriteMaker.pm b/lib/SVG/SpriteMaker.pm index c27a301..e24b5d9 100644 --- a/lib/SVG/SpriteMaker.pm +++ b/lib/SVG/SpriteMaker.pm @@ -27,6 +27,7 @@ sub make_sprite { 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) = @$_; @@ -38,6 +39,43 @@ sub make_sprite { $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); } @@ -108,6 +146,16 @@ used: 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 environment variable to a +true value. + =head1 SEE ALSO L, L diff --git a/svg-spritemaker b/svg-spritemaker index 3762063..22ed501 100755 --- a/svg-spritemaker +++ b/svg-spritemaker @@ -60,6 +60,16 @@ example in the SYNOPSIS). =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 environment variable to a +true value. + =head1 SEE ALSO L, L diff --git a/t/SVG-SpriteMaker.t b/t/SVG-SpriteMaker.t index b83a939..4c37199 100644 --- a/t/SVG-SpriteMaker.t +++ b/t/SVG-SpriteMaker.t @@ -2,11 +2,15 @@ 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 => ; 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_'; diff --git a/t/circle.svg b/t/circle.svg index 0e1ecb9..2affb79 100644 --- a/t/circle.svg +++ b/t/circle.svg @@ -1,3 +1,3 @@ - + diff --git a/t/rect.svg b/t/rect.svg index 955293d..803f33f 100644 --- a/t/rect.svg +++ b/t/rect.svg @@ -1,3 +1,3 @@ - +