Skip to content

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

@yangxu52

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

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