Skip to content

fix(class): support styling and callbacks for generic classes#7762

Open
Dharya-dev wants to merge 3 commits into
mermaid-js:developfrom
Dharya-dev:fix/class-diagram-generic-css
Open

fix(class): support styling and callbacks for generic classes#7762
Dharya-dev wants to merge 3 commits into
mermaid-js:developfrom
Dharya-dev:fix/class-diagram-generic-css

Conversation

@Dharya-dev
Copy link
Copy Markdown

@Dharya-dev Dharya-dev commented May 17, 2026

📑 Summary

Hey everyone! I noticed an issue where generic classes (like Class~T~) in class diagrams weren't receiving CSS styles or callback events properly. The parser was picking them up fine, but they weren't being normalized (stripping out the ~T~) before assigning the styles or interactivity handlers in classDb.ts. This PR fixes that!

Resolves #7753

📏 Design Decisions

  • I updated the setter functions in classDb.ts (specifically setCssClass, setTooltip, setLink, and setClickEvent) to normalize the class IDs. I used the existing splitClassNameAndType helper to strip the generic signatures before updating the class nodes in the DB.
  • I also added some regression tests to classDiagram.spec.ts to make sure styles apply correctly through both explicit class statements and shorthand syntax, and to verify the callback bindings on generic classes.

📋 Tasks

Make sure you

  • 📖 have read the contribution guidelines
  • 💻 have added necessary unit/e2e tests.
  • 📓 have added documentation. Make sure MERMAID_RELEASE_VERSION is used for all new features.
  • 🦋 If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. Changesets that add features should be minor and those that fix bugs should be patch. Please prefix changeset messages with feat:, fix:, or chore:.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 17, 2026

Deploy Preview for mermaid-js ready!

Name Link
🔨 Latest commit 9d8ad46
🔍 Latest deploy log https://app.netlify.com/projects/mermaid-js/deploys/6a0dd905bde99400082dea69
😎 Deploy Preview https://deploy-preview-7762--mermaid-js.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 17, 2026

🦋 Changeset detected

Latest commit: 9d8ad46

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
mermaid Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the Type: Bug / Error Something isn't working or is incorrect label May 17, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 17, 2026

Open in StackBlitz

@mermaid-js/examples

npm i https://pkg.pr.new/@mermaid-js/examples@7762

mermaid

npm i https://pkg.pr.new/mermaid@7762

@mermaid-js/layout-elk

npm i https://pkg.pr.new/@mermaid-js/layout-elk@7762

@mermaid-js/layout-tidy-tree

npm i https://pkg.pr.new/@mermaid-js/layout-tidy-tree@7762

@mermaid-js/mermaid-zenuml

npm i https://pkg.pr.new/@mermaid-js/mermaid-zenuml@7762

@mermaid-js/parser

npm i https://pkg.pr.new/@mermaid-js/parser@7762

@mermaid-js/tiny

npm i https://pkg.pr.new/@mermaid-js/tiny@7762

commit: 9d8ad46

@codecov
Copy link
Copy Markdown

codecov Bot commented May 17, 2026

Codecov Report

❌ Patch coverage is 0% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 3.26%. Comparing base (e575809) to head (9d8ad46).

Files with missing lines Patch % Lines
packages/mermaid/src/diagrams/class/classDb.ts 0.00% 13 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           develop   #7762      +/-   ##
==========================================
- Coverage     3.26%   3.26%   -0.01%     
==========================================
  Files          599     599              
  Lines        60766   60776      +10     
  Branches       917     917              
==========================================
  Hits          1986    1986              
- Misses       58780   58790      +10     
Flag Coverage Δ
unit 3.26% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
packages/mermaid/src/diagrams/class/classDb.ts 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@argos-ci
Copy link
Copy Markdown

argos-ci Bot commented May 17, 2026

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - May 20, 2026, 4:01 PM

Copy link
Copy Markdown
Collaborator

@knsv-bot knsv-bot left a comment

Choose a reason for hiding this comment

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

[sisyphus-bot]

Thanks for this, @Dharya-dev — really clean, well-scoped bug fix. 🎉 You correctly traced #7753 to its root cause: classes are stored in this.classes keyed by the bare className (addClassclassDb.ts:114-122), but the interactivity/style setters were looking them up with the full generic id (C1~T~), so the lookup silently missed for generic classes.

I checked this out locally and verified the behaviour:

  • Full class spec passes with the fix (382 tests green).
  • TDD check: reverting the source while keeping your new tests makes all 3 new tests fail, and they pass with the fix — so the tests genuinely capture the reported bug. 🎉
  • Ran a dedicated XSS/injection pass over the changes: no issues. The normalized id flows through splitClassNameAndTypecommon.sanitizeText (it's actually double-sanitized) and is only used as a Map key, the securityLevel !== 'loose' guard in setClickFunc is untouched, and sanitizeText/utils.formatUrl on tooltip/link are intact.

What's working well

  • 🎉 [praise] Reusing the existing splitClassNameAndType helper rather than ad-hoc ~-stripping keeps this consistent with how the rest of the file already normalizes ids (setClassLabel:100, addRelation:239-240, addClassesToNamespace:662).
  • 🎉 [praise] Replacing the fragile this.classes.get(id)! non-null assertions in setTooltip and setClickEvent with if (classNode) guards is a nice defensive improvement beyond the literal bug — a missing class id now no-ops instead of throwing.
  • 🎉 [praise] Changeset present, correct patch bump with fix: prefix, and the PR links the issue.

Things to address

  • 🟡 [important] — Test coverage gap for setTooltip and setLink. The fix touches five code paths (setCssClass, setTooltip, setLink, setClickEvent, setClickFunc), but the new tests only cover setCssClass (explicit + ::: shorthand) and the click/callback path. setTooltip and setLink on a generic class have no regression test, even though they had the exact same defect. It would be great to add two small tests so the full scope is locked down, e.g.:

    • tooltip: class C1~T~ + click C1~T~ call cb() "a tip" → assert classDb.getClass('C1').tooltip is set
    • link: class C1~T~ + link C1~T~ "https://example.com" → assert getClass('C1').link is set and cssClasses includes clickable
  • 🟢 [nit] Minor stylistic inconsistency within the diff: setCssClass/setLink reassign id = this.splitClassNameAndType(id).className; in place, while setTooltip/setClickEvent introduce a separate className const for the same operation. Both read fine — only worth tidying if you're already touching these lines.

  • 🟢 [nit] The snapshot change domId: "classId-Student-149""classId-Student-152" is just churn from the module-level classCounter being bumped by the new test classes added earlier in the file. The update is correct and expected — flagging only so it's clear this isn't an unintended behaviour change.

  • 💡 [suggestion] — out of scope, no action needed here. In setCssClass/setLink the if (/\d/.exec(_id[0])) digit-prefix branch runs before splitClassNameAndType, whereas addClass keys classes purely by splitClassNameAndType(...).className with no digit prefix. So a class that is both digit-leading and generic (class 1C~T~:::x) would still not resolve. This is a pre-existing inconsistency unrelated to #7753 — possible follow-up, not something to fix in this PR.

The fix itself is correct and well-targeted; the only real ask is rounding out regression coverage for the two untested setters. Let's get this across the finish line. 🙏

@Dharya-dev Dharya-dev force-pushed the fix/class-diagram-generic-css branch from c9bf018 to 0e4d733 Compare May 18, 2026 22:37
Dharya-dev and others added 2 commits May 19, 2026 04:08
Co-authored-by: Dharya-dev <Dharya-dev@users.noreply.github.com>
Adds missing test cases for setTooltip and setLink on generic classes (e.g. C1~T~) to cover the code paths introduced in the earlier fix. Updates the inline snapshot domId to account for the two new test-generated classes incrementing the module-level counter.
@Dharya-dev Dharya-dev force-pushed the fix/class-diagram-generic-css branch from 0e4d733 to cfd2391 Compare May 18, 2026 22:39
@Dharya-dev
Copy link
Copy Markdown
Author

Hi maintainers! 👋 Just wanted to give this a friendly bump. The recent commits add the required unit tests and address the coverage gaps. The PR should be ready for review. Please let me know if there are any other changes needed!

Copy link
Copy Markdown
Collaborator

@kedar49 kedar49 left a comment

Choose a reason for hiding this comment

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

splitClassNameAndType() normalization logic is now duplicated across multiple methods (setCssClass, setTooltip, setClickEvent, setClickFunc). It may be worth centralizing generic-class resolution into a helper to avoid future inconsistencies.

Copy link
Copy Markdown
Collaborator

@knsv-bot knsv-bot left a comment

Choose a reason for hiding this comment

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

[sisyphus-bot]

Thanks for the update, @Dharya-dev — this looks good to me now. 🎉

The latest changes round out the regression coverage for the full set of generic-class interaction paths: explicit cssClass, shorthand :::, callbacks, tooltips, and links. I also re-checked the implementation against #7753: class declarations with generic suffixes are stored under the normalized class name (C1), and the affected setters now normalize C1~T~ through splitClassNameAndType(...) before looking up the class node.

What's working well

  • 🎉 [praise] The fix stays nicely scoped to the class diagram DB paths that were doing class lookups with generic IDs.
  • 🎉 [praise] The new tests now cover all five changed behavior paths: CSS class assignment, shorthand CSS class assignment, callback binding, tooltip binding, and link binding.
  • 🎉 [praise] Replacing the previous non-null assertions in the click/tooltip paths with guarded lookups makes this a little more defensive without broadening the PR.
  • 🎉 [praise] Changeset is present and correctly marks this as a patch-level fix(class) change.

Security

No XSS or injection issues identified.

I checked the changed paths specifically:

  • tooltip text still goes through sanitizeText(...)
  • links still go through utils.formatUrl(...)
  • callback execution remains gated behind securityLevel === 'loose'
  • the new generic normalization only affects class lookup keys and does not introduce a new DOM/SVG sink

Things to address

Nothing blocking from my side.

One tiny non-blocking note: setCssClass / setLink mutate the local id variable, while setTooltip / setClickEvent introduce a className const for the same normalization step. Both are clear enough, so I wouldn’t ask for a change here unless you’re already touching those lines.

Looks ready to merge. 🙌

@knsv knsv enabled auto-merge May 20, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Type: Bug / Error Something isn't working or is incorrect

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Class diagram can't combine generic and cssClass suffixes

4 participants