Skip to content

fix: polyfill CSSStyleDeclaration for sequence diagrams#14

Merged
pilat merged 1 commit intomainfrom
fix/sequence-diagram-style-polyfill
Apr 28, 2026
Merged

fix: polyfill CSSStyleDeclaration for sequence diagrams#14
pilat merged 1 commit intomainfrom
fix/sequence-diagram-style-polyfill

Conversation

@pilat
Copy link
Copy Markdown
Owner

@pilat pilat commented Apr 27, 2026

Mermaid sequence diagrams were crashing with this.style.removeProperty is not a function.

The root cause is svgdom's broken .style implementation — it returns the element itself instead of a CSSStyleDeclaration object. D3 (bundled in mermaid) calls element.style.removeProperty() during sequence diagram rendering, which fails because there's no such method on the element.

Flowcharts work because htmlLabels: false bypasses most CSS manipulation, but sequence diagrams have a different code path that always hits these D3 style methods.

The fix adds a minimal CSSStyleDeclaration shim that parses and manipulates the style attribute string directly. It slots in with the other svgdom/elkjs compatibility patches in loadMermaid().

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced sequence diagram rendering to work reliably across different runtime environments by improving style attribute handling.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

Warning

Rate limit exceeded

@pilat has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 55 minutes and 47 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1b65fb8f-8fc5-4d30-a8fd-798db0b76d61

📥 Commits

Reviewing files that changed from the base of the PR and between b2a2417 and 84123a8.

📒 Files selected for processing (3)
  • src/mermaid/render.ts
  • src/mermaid/style-polyfill.ts
  • test/mermaid-elk.test.ts
📝 Walkthrough

Walkthrough

A runtime patch is added to loadMermaid that overrides SVGElement.prototype.style with a custom shim object capable of managing SVG style attributes. This enables sequence-diagram rendering without relying on a native CSSStyleDeclaration implementation in environments where it may be unavailable.

Changes

Cohort / File(s) Summary
SVG Style Attribute Shim
src/mermaid/render.ts
Injects a runtime patch within loadMermaid that replaces SVGElement.prototype.style with a custom getter returning a lightweight shim with getPropertyValue, setProperty, and removeProperty methods. The shim parses and rewrites the style attribute directly to handle style operations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A patch for the styles, so clever and neat,
Where SVGs dance without missing a beat,
No declarations needed, just attributes to parse,
A lightweight shim makes the sequences fast!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding a CSSStyleDeclaration polyfill to fix sequence diagram rendering issues.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sequence-diagram-style-polyfill

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@pilat pilat force-pushed the fix/sequence-diagram-style-polyfill branch from b2a2417 to e02c1c1 Compare April 27, 2026 23:58
@pilat pilat force-pushed the fix/sequence-diagram-style-polyfill branch from e02c1c1 to 84123a8 Compare April 27, 2026 23:59
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/mermaid/render.ts (1)

60-82: Regex patterns may incorrectly match property names that appear as substrings.

The current regex patterns search anywhere in the style string, which could match a property name that appears within another property name's text. For example, getPropertyValue('color') on background-color: red; would incorrectly return red because color: appears at position 11 in the string.

For SVG properties (fill/fill-opacity, stroke/stroke-width), this is safe since the base property is followed by - rather than :. However, for a more robust shim, anchoring the match to the start of string or after a semicolon would prevent edge cases.

Also, setProperty lacks the 'g' flag while removeProperty has it—this inconsistency could cause duplicate properties if setProperty is called when a property already appears multiple times.

Suggested fix with anchored regex patterns
 function createStyleShim(element: any) {
   return {
     getPropertyValue(name: string): string {
       const style = element.getAttribute('style') || ''
-      const match = style.match(new RegExp(name + '\\s*:\\s*([^;]+)'))
+      const match = style.match(new RegExp('(?:^|;)\\s*' + name + '\\s*:\\s*([^;]*)', 'i'))
       return match ? match[1].trim() : ''
     },
     setProperty(name: string, value: string): void {
       const style = element.getAttribute('style') || ''
-      const regex = new RegExp(name + '\\s*:[^;]+;?\\s*')
+      const regex = new RegExp('(?:^|;\\s*)' + name + '\\s*:[^;]*;?\\s*', 'gi')
       const cleaned = style.replace(regex, '')
       const newStyle = cleaned + (cleaned && !cleaned.endsWith(';') ? '; ' : '') + name + ': ' + value + ';'
       element.setAttribute('style', newStyle.trim())
     },
     removeProperty(name: string): string {
       const style = element.getAttribute('style') || ''
-      const regex = new RegExp(name + '\\s*:[^;]+;?\\s*', 'g')
+      const regex = new RegExp('(?:^|;\\s*)' + name + '\\s*:[^;]*;?\\s*', 'gi')
       const oldValue = this.getPropertyValue(name)
       element.setAttribute('style', style.replace(regex, '').trim())
       return oldValue
     },
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/mermaid/render.ts` around lines 60 - 82, The style-shim regexes in
createStyleShim can falsely match substrings and are inconsistent with flags;
update getPropertyValue, setProperty and removeProperty to anchor property
matches to the start of the style string or immediately after a semicolon (use a
pattern like (?:^|;\s*)<name>\s*:\s*([^;]+) ) so you only match whole property
occurrences, add the 'g' flag to the regex used in setProperty (to remove
duplicates before inserting), and keep existing trimming/semicolon logic in
setProperty and removeProperty so you remove all prior matches and insert a
single normalized "name: value;" string; reference functions: createStyleShim,
getPropertyValue, setProperty, removeProperty.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/mermaid/render.ts`:
- Around line 60-82: The style-shim regexes in createStyleShim can falsely match
substrings and are inconsistent with flags; update getPropertyValue, setProperty
and removeProperty to anchor property matches to the start of the style string
or immediately after a semicolon (use a pattern like
(?:^|;\s*)<name>\s*:\s*([^;]+) ) so you only match whole property occurrences,
add the 'g' flag to the regex used in setProperty (to remove duplicates before
inserting), and keep existing trimming/semicolon logic in setProperty and
removeProperty so you remove all prior matches and insert a single normalized
"name: value;" string; reference functions: createStyleShim, getPropertyValue,
setProperty, removeProperty.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b3e907d2-caf0-4cb0-8e48-f4c598bac9e8

📥 Commits

Reviewing files that changed from the base of the PR and between ca3e8cd and b2a2417.

📒 Files selected for processing (1)
  • src/mermaid/render.ts

@pilat pilat merged commit b0ff81a into main Apr 28, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant