Repository: mermaid-js/mermaid
File: packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts (TypeScript)

Code before:
      stroke: '#000',
      pos: actors[person].position,
    };
    svgDraw.drawCircle(diagram, circleData);

    const labelData = {
      x: 40,
      y: yPos + 7,
      fill: '#666',
      text: person,
      textMargin: conf.boxTextMargin | 5,
    };
    svgDraw.drawText(diagram, labelData);

    yPos += 20;
  });
}
// TODO: Cleanup?
const conf = getConfig().journey;
const LEFT_MARGIN = conf.leftMargin;
export const draw = function (text, id, version, diagObj) {
  const titleColor = conf.titleColor;
  const titleFontSize = conf.titleFontSize;
  const titleFontFamily = conf.titleFontFamily;

  const securityLevel = getConfig().securityLevel;
  // Handle root and Document for when rendering in sandbox mode
  let sandboxElement;
  if (securityLevel === 'sandbox') {
    sandboxElement = select('#i' + id);
  }
  const root =
    securityLevel === 'sandbox'
      ? select(sandboxElement.nodes()[0].contentDocument.body)
      : select('body');
  // const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;

  bounds.init();
  const diagram = root.select('#' + id);

  svgDraw.initGraphics(diagram);

  const tasks = diagObj.db.getTasks();
  const title = diagObj.db.getDiagramTitle();

  const actorNames = diagObj.db.getActors();
  for (const member in actors) {
    delete actors[member];
  }
  let actorPos = 0;
  actorNames.forEach((actorName) => {

Review comment (security):
Using the conf object will cause issues, as it's only initialized during the initial load.
Please use the configObject as before, and remove the getConfig() call for securityLevel 

Code after:
      r: 7,
      fill: colour,
      stroke: '#000',
      pos: actors[person].position,
    };
    svgDraw.drawCircle(diagram, circleData);

    // First, measure the full text width without wrapping.
    let measureText = diagram.append('text').attr('visibility', 'hidden').text(person);
    const fullTextWidth = measureText.node().getBoundingClientRect().width;
    measureText.remove();

    let lines = [];

    // If the text is naturally within the max width, use it as a single line.
    if (fullTextWidth <= maxLabelWidth) {
      lines = [person];
    } else {
      // Otherwise, wrap the text using the knuth-plass algorithm.
      const words = person.split(' '); // Split the text into words.
      let currentLine = '';
      measureText = diagram.append('text').attr('visibility', 'hidden');

      words.forEach((word) => {
        // check the width of the line with the new word.
        const testLine = currentLine ? `${currentLine} ${word}` : word;
        measureText.text(testLine);
        const textWidth = measureText.node().getBoundingClientRect().width;

        if (textWidth > maxLabelWidth) {
          // If adding the new word exceeds max width, push the current line.
          if (currentLine) {
            lines.push(currentLine);
          }
          currentLine = word; // Start a new line with the current word.

          // If the word itself is too long, break it with a hyphen.
          measureText.text(word);
          if (measureText.node().getBoundingClientRect().width > maxLabelWidth) {
            let brokenWord = '';
            for (const char of word) {
              brokenWord += char;
              measureText.text(brokenWord + '-');
              if (measureText.node().getBoundingClientRect().width > maxLabelWidth) {
                // Push the broken part with a hyphen.
                lines.push(brokenWord.slice(0, -1) + '-');
                brokenWord = char;
              }
            }
            currentLine = brokenWord;
          }