All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.dist.chunks.mermaid.core.chunk-2EDTWDYI.mjs Maven / Gradle / Ivy

Go to download

Markdown-ish syntax for generating flowcharts, mindmaps, sequence diagrams, class diagrams, gantt charts, git graphs and more.

There is a newer version: 11.4.0
Show newest version
import {
  __name,
  assignWithDepth_default,
  common_default,
  detectType,
  directiveRegex,
  log,
  sanitizeDirective
} from "./chunk-IIKMQLIC.mjs";

// src/utils.ts
import { sanitizeUrl } from "@braintree/sanitize-url";
import {
  curveBasis,
  curveBasisClosed,
  curveBasisOpen,
  curveBumpX,
  curveBumpY,
  curveBundle,
  curveCardinalClosed,
  curveCardinalOpen,
  curveCardinal,
  curveCatmullRomClosed,
  curveCatmullRomOpen,
  curveCatmullRom,
  curveLinear,
  curveLinearClosed,
  curveMonotoneX,
  curveMonotoneY,
  curveNatural,
  curveStep,
  curveStepAfter,
  curveStepBefore,
  select
} from "d3";
import memoize from "lodash-es/memoize.js";
import merge from "lodash-es/merge.js";
var ZERO_WIDTH_SPACE = "\u200B";
var d3CurveTypes = {
  curveBasis,
  curveBasisClosed,
  curveBasisOpen,
  curveBumpX,
  curveBumpY,
  curveBundle,
  curveCardinalClosed,
  curveCardinalOpen,
  curveCardinal,
  curveCatmullRomClosed,
  curveCatmullRomOpen,
  curveCatmullRom,
  curveLinear,
  curveLinearClosed,
  curveMonotoneX,
  curveMonotoneY,
  curveNatural,
  curveStep,
  curveStepAfter,
  curveStepBefore
};
var directiveWithoutOpen = /\s*(?:(\w+)(?=:):|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi;
var detectInit = /* @__PURE__ */ __name(function(text, config) {
  const inits = detectDirective(text, /(?:init\b)|(?:initialize\b)/);
  let results = {};
  if (Array.isArray(inits)) {
    const args = inits.map((init) => init.args);
    sanitizeDirective(args);
    results = assignWithDepth_default(results, [...args]);
  } else {
    results = inits.args;
  }
  if (!results) {
    return;
  }
  let type = detectType(text, config);
  const prop = "config";
  if (results[prop] !== void 0) {
    if (type === "flowchart-v2") {
      type = "flowchart";
    }
    results[type] = results[prop];
    delete results[prop];
  }
  return results;
}, "detectInit");
var detectDirective = /* @__PURE__ */ __name(function(text, type = null) {
  try {
    const commentWithoutDirectives = new RegExp(
      `[%]{2}(?![{]${directiveWithoutOpen.source})(?=[}][%]{2}).*
`,
      "ig"
    );
    text = text.trim().replace(commentWithoutDirectives, "").replace(/'/gm, '"');
    log.debug(
      `Detecting diagram directive${type !== null ? " type:" + type : ""} based on the text:${text}`
    );
    let match;
    const result = [];
    while ((match = directiveRegex.exec(text)) !== null) {
      if (match.index === directiveRegex.lastIndex) {
        directiveRegex.lastIndex++;
      }
      if (match && !type || type && match[1]?.match(type) || type && match[2]?.match(type)) {
        const type2 = match[1] ? match[1] : match[2];
        const args = match[3] ? match[3].trim() : match[4] ? JSON.parse(match[4].trim()) : null;
        result.push({ type: type2, args });
      }
    }
    if (result.length === 0) {
      return { type: text, args: null };
    }
    return result.length === 1 ? result[0] : result;
  } catch (error) {
    log.error(
      `ERROR: ${error.message} - Unable to parse directive type: '${type}' based on the text: '${text}'`
    );
    return { type: void 0, args: null };
  }
}, "detectDirective");
var removeDirectives = /* @__PURE__ */ __name(function(text) {
  return text.replace(directiveRegex, "");
}, "removeDirectives");
var isSubstringInArray = /* @__PURE__ */ __name(function(str, arr) {
  for (const [i, element] of arr.entries()) {
    if (element.match(str)) {
      return i;
    }
  }
  return -1;
}, "isSubstringInArray");
function interpolateToCurve(interpolate, defaultCurve) {
  if (!interpolate) {
    return defaultCurve;
  }
  const curveName = `curve${interpolate.charAt(0).toUpperCase() + interpolate.slice(1)}`;
  return d3CurveTypes[curveName] ?? defaultCurve;
}
__name(interpolateToCurve, "interpolateToCurve");
function formatUrl(linkStr, config) {
  const url = linkStr.trim();
  if (!url) {
    return void 0;
  }
  if (config.securityLevel !== "loose") {
    return sanitizeUrl(url);
  }
  return url;
}
__name(formatUrl, "formatUrl");
var runFunc = /* @__PURE__ */ __name((functionName, ...params) => {
  const arrPaths = functionName.split(".");
  const len = arrPaths.length - 1;
  const fnName = arrPaths[len];
  let obj = window;
  for (let i = 0; i < len; i++) {
    obj = obj[arrPaths[i]];
    if (!obj) {
      log.error(`Function name: ${functionName} not found in window`);
      return;
    }
  }
  obj[fnName](...params);
}, "runFunc");
function distance(p1, p2) {
  if (!p1 || !p2) {
    return 0;
  }
  return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}
__name(distance, "distance");
function traverseEdge(points) {
  let prevPoint;
  let totalDistance = 0;
  points.forEach((point) => {
    totalDistance += distance(point, prevPoint);
    prevPoint = point;
  });
  const remainingDistance = totalDistance / 2;
  return calculatePoint(points, remainingDistance);
}
__name(traverseEdge, "traverseEdge");
function calcLabelPosition(points) {
  if (points.length === 1) {
    return points[0];
  }
  return traverseEdge(points);
}
__name(calcLabelPosition, "calcLabelPosition");
var roundNumber = /* @__PURE__ */ __name((num, precision = 2) => {
  const factor = Math.pow(10, precision);
  return Math.round(num * factor) / factor;
}, "roundNumber");
var calculatePoint = /* @__PURE__ */ __name((points, distanceToTraverse) => {
  let prevPoint = void 0;
  let remainingDistance = distanceToTraverse;
  for (const point of points) {
    if (prevPoint) {
      const vectorDistance = distance(point, prevPoint);
      if (vectorDistance < remainingDistance) {
        remainingDistance -= vectorDistance;
      } else {
        const distanceRatio = remainingDistance / vectorDistance;
        if (distanceRatio <= 0) {
          return prevPoint;
        }
        if (distanceRatio >= 1) {
          return { x: point.x, y: point.y };
        }
        if (distanceRatio > 0 && distanceRatio < 1) {
          return {
            x: roundNumber((1 - distanceRatio) * prevPoint.x + distanceRatio * point.x, 5),
            y: roundNumber((1 - distanceRatio) * prevPoint.y + distanceRatio * point.y, 5)
          };
        }
      }
    }
    prevPoint = point;
  }
  throw new Error("Could not find a suitable point for the given distance");
}, "calculatePoint");
var calcCardinalityPosition = /* @__PURE__ */ __name((isRelationTypePresent, points, initialPosition) => {
  log.info(`our points ${JSON.stringify(points)}`);
  if (points[0] !== initialPosition) {
    points = points.reverse();
  }
  const distanceToCardinalityPoint = 25;
  const center = calculatePoint(points, distanceToCardinalityPoint);
  const d = isRelationTypePresent ? 10 : 5;
  const angle = Math.atan2(points[0].y - center.y, points[0].x - center.x);
  const cardinalityPosition = { x: 0, y: 0 };
  cardinalityPosition.x = Math.sin(angle) * d + (points[0].x + center.x) / 2;
  cardinalityPosition.y = -Math.cos(angle) * d + (points[0].y + center.y) / 2;
  return cardinalityPosition;
}, "calcCardinalityPosition");
function calcTerminalLabelPosition(terminalMarkerSize, position, _points) {
  const points = structuredClone(_points);
  log.info("our points", points);
  if (position !== "start_left" && position !== "start_right") {
    points.reverse();
  }
  const distanceToCardinalityPoint = 25 + terminalMarkerSize;
  const center = calculatePoint(points, distanceToCardinalityPoint);
  const d = 10 + terminalMarkerSize * 0.5;
  const angle = Math.atan2(points[0].y - center.y, points[0].x - center.x);
  const cardinalityPosition = { x: 0, y: 0 };
  if (position === "start_left") {
    cardinalityPosition.x = Math.sin(angle + Math.PI) * d + (points[0].x + center.x) / 2;
    cardinalityPosition.y = -Math.cos(angle + Math.PI) * d + (points[0].y + center.y) / 2;
  } else if (position === "end_right") {
    cardinalityPosition.x = Math.sin(angle - Math.PI) * d + (points[0].x + center.x) / 2 - 5;
    cardinalityPosition.y = -Math.cos(angle - Math.PI) * d + (points[0].y + center.y) / 2 - 5;
  } else if (position === "end_left") {
    cardinalityPosition.x = Math.sin(angle) * d + (points[0].x + center.x) / 2 - 5;
    cardinalityPosition.y = -Math.cos(angle) * d + (points[0].y + center.y) / 2 - 5;
  } else {
    cardinalityPosition.x = Math.sin(angle) * d + (points[0].x + center.x) / 2;
    cardinalityPosition.y = -Math.cos(angle) * d + (points[0].y + center.y) / 2;
  }
  return cardinalityPosition;
}
__name(calcTerminalLabelPosition, "calcTerminalLabelPosition");
function getStylesFromArray(arr) {
  let style = "";
  let labelStyle = "";
  for (const element of arr) {
    if (element !== void 0) {
      if (element.startsWith("color:") || element.startsWith("text-align:")) {
        labelStyle = labelStyle + element + ";";
      } else {
        style = style + element + ";";
      }
    }
  }
  return { style, labelStyle };
}
__name(getStylesFromArray, "getStylesFromArray");
var cnt = 0;
var generateId = /* @__PURE__ */ __name(() => {
  cnt++;
  return "id-" + Math.random().toString(36).substr(2, 12) + "-" + cnt;
}, "generateId");
function makeRandomHex(length) {
  let result = "";
  const characters = "0123456789abcdef";
  const charactersLength = characters.length;
  for (let i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}
__name(makeRandomHex, "makeRandomHex");
var random = /* @__PURE__ */ __name((options) => {
  return makeRandomHex(options.length);
}, "random");
var getTextObj = /* @__PURE__ */ __name(function() {
  return {
    x: 0,
    y: 0,
    fill: void 0,
    anchor: "start",
    style: "#666",
    width: 100,
    height: 100,
    textMargin: 0,
    rx: 0,
    ry: 0,
    valign: void 0,
    text: ""
  };
}, "getTextObj");
var drawSimpleText = /* @__PURE__ */ __name(function(elem, textData) {
  const nText = textData.text.replace(common_default.lineBreakRegex, " ");
  const [, _fontSizePx] = parseFontSize(textData.fontSize);
  const textElem = elem.append("text");
  textElem.attr("x", textData.x);
  textElem.attr("y", textData.y);
  textElem.style("text-anchor", textData.anchor);
  textElem.style("font-family", textData.fontFamily);
  textElem.style("font-size", _fontSizePx);
  textElem.style("font-weight", textData.fontWeight);
  textElem.attr("fill", textData.fill);
  if (textData.class !== void 0) {
    textElem.attr("class", textData.class);
  }
  const span = textElem.append("tspan");
  span.attr("x", textData.x + textData.textMargin * 2);
  span.attr("fill", textData.fill);
  span.text(nText);
  return textElem;
}, "drawSimpleText");
var wrapLabel = memoize(
  (label, maxWidth, config) => {
    if (!label) {
      return label;
    }
    config = Object.assign(
      { fontSize: 12, fontWeight: 400, fontFamily: "Arial", joinWith: "
" }, config ); if (common_default.lineBreakRegex.test(label)) { return label; } const words = label.split(" ").filter(Boolean); const completedLines = []; let nextLine = ""; words.forEach((word, index) => { const wordLength = calculateTextWidth(`${word} `, config); const nextLineLength = calculateTextWidth(nextLine, config); if (wordLength > maxWidth) { const { hyphenatedStrings, remainingWord } = breakString(word, maxWidth, "-", config); completedLines.push(nextLine, ...hyphenatedStrings); nextLine = remainingWord; } else if (nextLineLength + wordLength >= maxWidth) { completedLines.push(nextLine); nextLine = word; } else { nextLine = [nextLine, word].filter(Boolean).join(" "); } const currentWord = index + 1; const isLastWord = currentWord === words.length; if (isLastWord) { completedLines.push(nextLine); } }); return completedLines.filter((line) => line !== "").join(config.joinWith); }, (label, maxWidth, config) => `${label}${maxWidth}${config.fontSize}${config.fontWeight}${config.fontFamily}${config.joinWith}` ); var breakString = memoize( (word, maxWidth, hyphenCharacter = "-", config) => { config = Object.assign( { fontSize: 12, fontWeight: 400, fontFamily: "Arial", margin: 0 }, config ); const characters = [...word]; const lines = []; let currentLine = ""; characters.forEach((character, index) => { const nextLine = `${currentLine}${character}`; const lineWidth = calculateTextWidth(nextLine, config); if (lineWidth >= maxWidth) { const currentCharacter = index + 1; const isLastLine = characters.length === currentCharacter; const hyphenatedNextLine = `${nextLine}${hyphenCharacter}`; lines.push(isLastLine ? nextLine : hyphenatedNextLine); currentLine = ""; } else { currentLine = nextLine; } }); return { hyphenatedStrings: lines, remainingWord: currentLine }; }, (word, maxWidth, hyphenCharacter = "-", config) => `${word}${maxWidth}${hyphenCharacter}${config.fontSize}${config.fontWeight}${config.fontFamily}` ); function calculateTextHeight(text, config) { return calculateTextDimensions(text, config).height; } __name(calculateTextHeight, "calculateTextHeight"); function calculateTextWidth(text, config) { return calculateTextDimensions(text, config).width; } __name(calculateTextWidth, "calculateTextWidth"); var calculateTextDimensions = memoize( (text, config) => { const { fontSize = 12, fontFamily = "Arial", fontWeight = 400 } = config; if (!text) { return { width: 0, height: 0 }; } const [, _fontSizePx] = parseFontSize(fontSize); const fontFamilies = ["sans-serif", fontFamily]; const lines = text.split(common_default.lineBreakRegex); const dims = []; const body = select("body"); if (!body.remove) { return { width: 0, height: 0, lineHeight: 0 }; } const g = body.append("svg"); for (const fontFamily2 of fontFamilies) { let cHeight = 0; const dim = { width: 0, height: 0, lineHeight: 0 }; for (const line of lines) { const textObj = getTextObj(); textObj.text = line || ZERO_WIDTH_SPACE; const textElem = drawSimpleText(g, textObj).style("font-size", _fontSizePx).style("font-weight", fontWeight).style("font-family", fontFamily2); const bBox = (textElem._groups || textElem)[0][0].getBBox(); if (bBox.width === 0 && bBox.height === 0) { throw new Error("svg element not in render tree"); } dim.width = Math.round(Math.max(dim.width, bBox.width)); cHeight = Math.round(bBox.height); dim.height += cHeight; dim.lineHeight = Math.round(Math.max(dim.lineHeight, cHeight)); } dims.push(dim); } g.remove(); const index = isNaN(dims[1].height) || isNaN(dims[1].width) || isNaN(dims[1].lineHeight) || dims[0].height > dims[1].height && dims[0].width > dims[1].width && dims[0].lineHeight > dims[1].lineHeight ? 0 : 1; return dims[index]; }, (text, config) => `${text}${config.fontSize}${config.fontWeight}${config.fontFamily}` ); var InitIDGenerator = class { constructor(deterministic = false, seed) { this.count = 0; this.count = seed ? seed.length : 0; this.next = deterministic ? () => this.count++ : () => Date.now(); } static { __name(this, "InitIDGenerator"); } }; var decoder; var entityDecode = /* @__PURE__ */ __name(function(html) { decoder = decoder || document.createElement("div"); html = escape(html).replace(/%26/g, "&").replace(/%23/g, "#").replace(/%3B/g, ";"); decoder.innerHTML = html; return unescape(decoder.textContent); }, "entityDecode"); function isDetailedError(error) { return "str" in error; } __name(isDetailedError, "isDetailedError"); var insertTitle = /* @__PURE__ */ __name((parent, cssClass, titleTopMargin, title) => { if (!title) { return; } const bounds = parent.node()?.getBBox(); if (!bounds) { return; } parent.append("text").text(title).attr("x", bounds.x + bounds.width / 2).attr("y", -titleTopMargin).attr("class", cssClass); }, "insertTitle"); var parseFontSize = /* @__PURE__ */ __name((fontSize) => { if (typeof fontSize === "number") { return [fontSize, fontSize + "px"]; } const fontSizeNumber = parseInt(fontSize ?? "", 10); if (Number.isNaN(fontSizeNumber)) { return [void 0, void 0]; } else if (fontSize === String(fontSizeNumber)) { return [fontSizeNumber, fontSize + "px"]; } else { return [fontSizeNumber, fontSize]; } }, "parseFontSize"); function cleanAndMerge(defaultData, data) { return merge({}, defaultData, data); } __name(cleanAndMerge, "cleanAndMerge"); var utils_default = { assignWithDepth: assignWithDepth_default, wrapLabel, calculateTextHeight, calculateTextWidth, calculateTextDimensions, cleanAndMerge, detectInit, detectDirective, isSubstringInArray, interpolateToCurve, calcLabelPosition, calcCardinalityPosition, calcTerminalLabelPosition, formatUrl, getStylesFromArray, generateId, random, runFunc, entityDecode, insertTitle, parseFontSize, InitIDGenerator }; var encodeEntities = /* @__PURE__ */ __name(function(text) { let txt = text; txt = txt.replace(/style.*:\S*#.*;/g, function(s) { return s.substring(0, s.length - 1); }); txt = txt.replace(/classDef.*:\S*#.*;/g, function(s) { return s.substring(0, s.length - 1); }); txt = txt.replace(/#\w+;/g, function(s) { const innerTxt = s.substring(1, s.length - 1); const isInt = /^\+?\d+$/.test(innerTxt); if (isInt) { return "\uFB02\xB0\xB0" + innerTxt + "\xB6\xDF"; } else { return "\uFB02\xB0" + innerTxt + "\xB6\xDF"; } }); return txt; }, "encodeEntities"); var decodeEntities = /* @__PURE__ */ __name(function(text) { return text.replace(/fl°°/g, "&#").replace(/fl°/g, "&").replace(/¶ß/g, ";"); }, "decodeEntities"); var getEdgeId = /* @__PURE__ */ __name((from, to, { counter = 0, prefix, suffix }) => { return `${prefix ? `${prefix}_` : ""}${from}_${to}_${counter}${suffix ? `_${suffix}` : ""}`; }, "getEdgeId"); export { ZERO_WIDTH_SPACE, removeDirectives, interpolateToCurve, getStylesFromArray, generateId, random, wrapLabel, calculateTextHeight, calculateTextWidth, isDetailedError, parseFontSize, cleanAndMerge, utils_default, encodeEntities, decodeEntities, getEdgeId };




© 2015 - 2024 Weber Informatics LLC | Privacy Policy