Skip to content

prefixIds does not correctly handle SMIL begin/end with offsets (e.g. ".end-0.5s") #2207

Description

@yangxu52

Describe the bug
The prefixIds plugin does not correctly prefix IDs referenced in SMIL animation timing attributes (begin / end) when offsets are present.

Currently, only values that strictly end with .end or .start are handled. However, valid SMIL syntax allows offsets such as:

  • a.end-0.5s
  • b.begin+0.1s

These are not processed, resulting in broken references after prefixing.

To Reproduce
1.SVGO config

{
  plugins: [
    'cleanupIds',
    {
      name: 'prefixIds',
      params: {
        prefix: 'icon',
        delim: '-'
      }
    }
  ]
}
  1. Input SVG
<svg>
  <circle>
    <animate
      id="a"
      attributeName="r"
      begin="0;b.end-0.5s"
      dur="1s"
      values="0;10;0" />
  </circle>
  <circle>
    <animate
      id="b"
      attributeName="r"
      begin="a.begin+0.1s"
      dur="1s"
      values="0;10;0" />
  </circle>
</svg>

Expected behavior
All ID references should be consistently prefixed:

begin="0;icon-b.end-0.5s"
begin="icon-a.begin+0.1s"

Actual behavior
Only IDs are prefixed, but references inside begin remain unchanged:

begin="0;b.end-0.5s"
begin="a.begin+0.1s"

This breaks animation chaining.

Root cause
The current implementation only matches:

val.endsWith('.end') || val.endsWith('.start')

This fails for valid SMIL expressions with offsets.

Suggested fix
Instead of checking only suffix, parse the SMIL timing value with a regex:

/^([a-zA-Z0-9_-]+)\.(begin|end)([+-].+)?$/

and prefix the ID part accordingly.

Screenshots

Image

Desktop (please complete the following information):

  • SVGO Version 4.0.1
  • Node.js Version 24
  • OS: Windows10

Additional context
SMIL timing syntax supports offsets:
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/begin

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions