Skip to content

fix: keep explicit line breaks in every wrapped label - #8038

Closed
Jaybhade wants to merge 1 commit into
mermaid-js:developfrom
Jaybhade:bug/8037_wrap-label-line-breaks
Closed

Jaybhade wants to merge 1 commit into
mermaid-js:developfrom
Jaybhade:bug/8037_wrap-label-line-breaks

Conversation

@Jaybhade

@Jaybhade Jaybhade commented Aug 7, 2026 •

Copy link
Copy Markdown

📑 Summary

Resolves #8037

lineBreakRegex is declared global (/<br\s*\/?>/gi) because sanitizeText and splitBreaks need it that way, but two call sites used it with .test():

  • hasBreaks() in packages/mermaid/src/diagrams/common/common.ts
  • wrapLabel() in packages/mermaid/src/utils.ts, in the early return that leaves an already-broken label alone

RegExp.prototype.test on a global regex advances lastIndex and leaves it set. The next check then starts mid-string, so a <br/> sitting before that offset is not found, wrapLabel falls through to its word-wrapping branch, and it rewrites a label the author had already broken by hand.

In a sequence diagram this means the message after a message containing a <br/> loses its line break and is re-flowed:

sequenceDiagram
  Alice->>Alice: wrap: aaa bbb ccc ddd eee fff ggg hhh iii jjj<br/>kkk
  Alice->>Alice: wrap: lll<br/>mmm nnn ooo ppp qqq rrr sss ttt uuu vvv
before after
message 1 aaa bbb ccc ddd eee fff ggg hhh iii jjj / kkk unchanged
message 2 lll / mmm nnn ooo ppp / qqq rrr sss ttt uuu / vvv lll / mmm nnn ooo ppp qqq rrr sss ttt uuu vvv

📏 Design Decisions

hasBreaks now uses String.prototype.search, which ignores lastIndex and restores it, so the shared regex keeps working for the replace/split callers that rely on the global flag. wrapLabel calls common.hasBreaks(label) instead of reaching for the regex itself, so there is one place left that decides whether a label already has breaks.

The alternative — a second, non-global copy of the pattern — would put the <br> pattern in two places, and clearing lastIndex before each test would still leave it dirty for the next caller.

📋 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:.

Documentation is unchanged — this restores the documented behaviour of <br/> rather than adding to it.

Tests added, each failing on develop and passing here:

  • hasBreaks gives the same answer on repeated calls (common.spec.ts)
  • wrapLabel leaves every label with line breaks untouched, not just the first one (utils.spec.ts)

vitest run is green: 226 files, 5091 passed / 16 skipped / 2 todo. pnpm lint is clean.

What's working well

  • 🎉 Replaces stateful global-regex .test() calls with search() in hasBreaks().
  • 🎉 Makes wrapLabel() use common.hasBreaks().
  • 🎉 Adds regression tests for repeated detection and multiple labels with <br/> breaks.
  • 🎉 Includes a patch changeset.

Review result

✅ Approve

The fix addresses stale lastIndex state and preserves explicit breaks across wrapped labels. No API or documentation changes are introduced.

lineBreakRegex is global so that sanitizeText and splitBreaks can use it,
but hasBreaks and wrapLabel checked it with .test(), which advances and
keeps lastIndex. The next check therefore started mid-string and missed a
<br/> placed before that offset, so wrapLabel re-wrapped a label whose
line breaks the author had written by hand.

Closes mermaid-js#8037
@changeset-bot

changeset-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 709e383

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

@netlify

netlify Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

❌ Deploy Preview for mermaid-js failed.

Name Link
🔨 Latest commit 709e383
🔍 Latest deploy log https://app.netlify.com/projects/mermaid-js/deploys/6a7638c05e39110008bc8952

@github-actions github-actions Bot added the Type: Bug / Error Something isn't working or is incorrect label Aug 7, 2026
@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7cc29e4c-20e2-4ccc-a5ba-b3dde5075e45

📥 Commits

Reviewing files that changed from the base of the PR and between 3d521b1 and 709e383.

📒 Files selected for processing (5)
  • .changeset/fix-wrap-label-line-breaks.md
  • packages/mermaid/src/diagrams/common/common.spec.ts
  • packages/mermaid/src/diagrams/common/common.ts
  • packages/mermaid/src/utils.spec.ts
  • packages/mermaid/src/utils.ts

📝 Walkthrough

Walkthrough

Mermaid now detects existing <br> breaks without shared regular-expression state. Label wrapping preserves explicit breaks across repeated and independent calls. Tests cover break variants and sequential label wrapping.

Changes

Label break preservation

Layer / File(s) Summary
Break detection and wrapping
packages/mermaid/src/diagrams/common/common.ts, packages/mermaid/src/utils.ts
hasBreaks uses search, and wrapLabel uses common.hasBreaks to detect existing breaks.
Break preservation validation
packages/mermaid/src/diagrams/common/common.spec.ts, packages/mermaid/src/utils.spec.ts, .changeset/fix-wrap-label-line-breaks.md
Tests cover break-tag variants, repeated calls, and independent wrapped labels. The changeset documents the patch.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: aloisklink

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary fix for preserving explicit line breaks in wrapped labels.
Description check ✅ Passed The description includes the summary, design decisions, issue reference, tests, lint results, and a justified documentation omission.
Linked Issues check ✅ Passed The changes address issue #8037 by preventing stale global-regex state and preserving explicit breaks across repeated label wrapping.
Out of Scope Changes check ✅ Passed The code changes, regression tests, and patch changeset all directly support the linked issue and stated pull request objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@pkg-pr-new

pkg-pr-new Bot commented Aug 7, 2026

Copy link
Copy Markdown

Open in StackBlitz

@mermaid-js/examples

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

mermaid

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

@mermaid-js/layout-elk

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

@mermaid-js/layout-tidy-tree

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

@mermaid-js/mermaid-zenuml

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

@mermaid-js/parser

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

@mermaid-js/tiny

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

commit: 709e383

@codecov

codecov Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 77.68%. Comparing base (3d521b1) to head (709e383).

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #8038      +/-   ##
===========================================
+ Coverage    77.61%   77.68%   +0.07%     
===========================================
  Files          568      568              
  Lines        74992    74992              
  Branches     12690    12691       +1     
===========================================
+ Hits         58202    58255      +53     
+ Misses       15796    15744      -52     
+ Partials       994      993       -1     
Flag Coverage Δ
e2e 70.71% <100.00%> (+0.14%) ⬆️
unit 75.05% <100.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/common/common.ts 76.29% <100.00%> (+0.86%) ⬆️
packages/mermaid/src/utils.ts 85.11% <100.00%> (-0.18%) ⬇️

... and 6 files with indirect coverage changes

🚀 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

argos-ci Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

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

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Aug 7, 2026, 8:18 PM

@Jaybhade

Copy link
Copy Markdown
Author

Superseded — a6ec7ff (fix: treat
as a line break in labels) is on develop and already carries this fix: hasBreaks() now tests a non-global twin of lineBreakRegex instead of the global one, and wrapLabel() goes through hasBreaks() rather than calling .test() on the shared regex, so the lastIndex carry-over that made an explicit <br/> disappear is gone. Its utils.ts change is identical to the one here, and it widens the regex to accept </br> on top.

I checked out develop clean, dropped in only the two spec files from this branch and ran them — 82 passing with none of my source changes — so there's nothing left here to land. Closing; this branch is conflicting against develop anyway. Thanks!

@Jaybhade Jaybhade closed this Aug 24, 2026
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.

Sequence diagram: explicit <br/> is ignored in the label after a label that has one

1 participant