mermaid/packages/mermaid/src/diagrams/sequence/sequenceDb.js

486 lines
12 KiB
JavaScript
Raw Normal View History

import mermaidAPI from '../../mermaidAPI';
import * as configApi from '../../config';
2021-02-06 11:26:05 +01:00
import { log } from '../../logger';
import { sanitizeText } from '../common/common';
import {
2022-05-17 20:23:45 +02:00
setAccTitle,
getAccTitle,
setDiagramTitle,
getDiagramTitle,
getAccDescription,
setAccDescription,
clear as commonClear,
} from '../../commonDb';
2017-09-10 13:41:34 +02:00
let prevActor = undefined;
2019-09-12 21:55:10 +02:00
let actors = {};
let messages = [];
const notes = [];
let sequenceNumbersEnabled = false;
2022-07-20 14:39:01 +02:00
let wrapEnabled;
2021-07-15 11:35:12 +02:00
export const parseDirective = function (statement, context, type) {
mermaidAPI.parseDirective(this, statement, context, type);
};
export const addActor = function (id, name, description, type) {
2017-04-16 17:48:36 +02:00
// Don't allow description nulling
2019-09-12 21:55:10 +02:00
const old = actors[id];
if (old && name === old.name && description == null) return;
2017-04-16 17:48:36 +02:00
// Don't allow null descriptions, either
if (description == null || description.text == null) {
description = { text: name, wrap: null, type };
}
if (type == null || description.text == null) {
description = { text: name, wrap: null, type };
}
2019-09-12 21:55:10 +02:00
actors[id] = {
name: name,
description: description.text,
2020-06-17 11:54:24 +02:00
wrap: (description.wrap === undefined && autoWrap()) || !!description.wrap,
prevActor: prevActor,
links: {},
properties: {},
actorCnt: null,
rectData: null,
2021-09-18 10:05:53 +02:00
type: type || 'participant',
};
if (prevActor && actors[prevActor]) {
actors[prevActor].nextActor = id;
}
prevActor = id;
2019-09-12 21:55:10 +02:00
};
2021-07-15 11:35:12 +02:00
const activationCount = (part) => {
let i;
let count = 0;
for (i = 0; i < messages.length; i++) {
if (messages[i].type === LINETYPE.ACTIVE_START) {
if (messages[i].from.actor === part) {
count++;
}
}
if (messages[i].type === LINETYPE.ACTIVE_END) {
if (messages[i].from.actor === part) {
count--;
}
}
}
return count;
};
2021-07-15 11:35:12 +02:00
export const addMessage = function (idFrom, idTo, message, answer) {
messages.push({
from: idFrom,
to: idTo,
message: message.text,
2020-06-17 11:54:24 +02:00
wrap: (message.wrap === undefined && autoWrap()) || !!message.wrap,
2021-07-15 11:35:12 +02:00
answer: answer,
});
2019-09-12 21:55:10 +02:00
};
2021-07-15 11:35:12 +02:00
export const addSignal = function (
2020-06-17 11:54:24 +02:00
idFrom,
idTo,
message = { text: undefined, wrap: undefined },
messageType
) {
if (messageType === LINETYPE.ACTIVE_END) {
const cnt = activationCount(idFrom.actor);
if (cnt < 1) {
// Bail out as there is an activation signal from an inactive participant
let error = new Error('Trying to inactivate an inactive participant (' + idFrom.actor + ')');
error.hash = {
text: '->>-',
token: '->>-',
line: '1',
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
2021-07-15 11:35:12 +02:00
expected: ["'ACTIVE_PARTICIPANT'"],
};
throw error;
}
}
messages.push({
from: idFrom,
to: idTo,
message: message.text,
2020-06-17 11:54:24 +02:00
wrap: (message.wrap === undefined && autoWrap()) || !!message.wrap,
2021-07-15 11:35:12 +02:00
type: messageType,
});
return true;
2019-09-12 21:55:10 +02:00
};
2021-07-15 11:35:12 +02:00
export const getMessages = function () {
2019-09-12 21:55:10 +02:00
return messages;
};
2021-07-15 11:35:12 +02:00
export const getActors = function () {
2019-09-12 21:55:10 +02:00
return actors;
};
2021-07-15 11:35:12 +02:00
export const getActor = function (id) {
2019-09-12 21:55:10 +02:00
return actors[id];
};
2021-07-15 11:35:12 +02:00
export const getActorKeys = function () {
2019-09-12 21:55:10 +02:00
return Object.keys(actors);
};
2021-07-15 11:35:12 +02:00
export const enableSequenceNumbers = function () {
sequenceNumbersEnabled = true;
};
export const disableSequenceNumbers = function () {
sequenceNumbersEnabled = false;
};
export const showSequenceNumbers = () => sequenceNumbersEnabled;
2019-09-12 21:55:10 +02:00
2021-07-15 11:35:12 +02:00
export const setWrap = function (wrapSetting) {
2020-06-17 11:54:24 +02:00
wrapEnabled = wrapSetting;
};
2022-07-18 16:00:03 +02:00
export const autoWrap = () => {
// if setWrap has been called, use that value, otherwise use the value from the config
// TODO: refactor, always use the config value let setWrap update the config value
if (typeof wrapEnabled !== 'undefined') {
return wrapEnabled;
}
return configApi.getConfig().sequence.wrap;
};
2021-07-15 11:35:12 +02:00
export const clear = function () {
2019-09-12 21:55:10 +02:00
actors = {};
messages = [];
2022-03-11 09:32:04 +01:00
sequenceNumbersEnabled = false;
commonClear();
};
2021-07-15 11:35:12 +02:00
export const parseMessage = function (str) {
const _str = str.trim();
const message = {
text: _str.replace(/^[:]?(?:no)?wrap:/, '').trim(),
wrap:
_str.match(/^[:]?wrap:/) !== null
? true
: _str.match(/^[:]?nowrap:/) !== null
? false
2021-07-15 11:35:12 +02:00
: undefined,
};
2021-02-06 11:26:05 +01:00
log.debug('parseMessage:', message);
return message;
2019-09-12 21:55:10 +02:00
};
2014-12-04 17:58:05 +01:00
2017-09-10 15:23:04 +02:00
export const LINETYPE = {
2017-04-11 16:14:25 +02:00
SOLID: 0,
DOTTED: 1,
NOTE: 2,
SOLID_CROSS: 3,
DOTTED_CROSS: 4,
SOLID_OPEN: 5,
DOTTED_OPEN: 6,
LOOP_START: 10,
LOOP_END: 11,
ALT_START: 12,
ALT_ELSE: 13,
ALT_END: 14,
OPT_START: 15,
OPT_END: 16,
ACTIVE_START: 17,
ACTIVE_END: 18,
PAR_START: 19,
PAR_AND: 20,
2019-07-23 07:47:49 +02:00
PAR_END: 21,
RECT_START: 22,
RECT_END: 23,
SOLID_POINT: 24,
2021-07-15 11:35:12 +02:00
DOTTED_POINT: 25,
AUTONUMBER: 26,
CRITICAL_START: 27,
CRITICAL_OPTION: 28,
CRITICAL_END: 29,
BREAK_START: 30,
BREAK_END: 31,
2019-09-12 21:55:10 +02:00
};
2014-12-04 17:58:05 +01:00
2017-09-10 15:23:04 +02:00
export const ARROWTYPE = {
2017-04-11 16:14:25 +02:00
FILLED: 0,
2021-07-15 11:35:12 +02:00
OPEN: 1,
2019-09-12 21:55:10 +02:00
};
2014-12-04 17:58:05 +01:00
2017-09-10 15:23:04 +02:00
export const PLACEMENT = {
2017-04-11 16:14:25 +02:00
LEFTOF: 0,
RIGHTOF: 1,
2021-07-15 11:35:12 +02:00
OVER: 2,
2019-09-12 21:55:10 +02:00
};
2014-12-04 17:58:05 +01:00
2021-07-15 11:35:12 +02:00
export const addNote = function (actor, placement, message) {
const note = {
actor: actor,
placement: placement,
message: message.text,
2021-07-15 11:35:12 +02:00
wrap: (message.wrap === undefined && autoWrap()) || !!message.wrap,
};
2014-12-04 17:58:05 +01:00
2017-04-16 17:48:36 +02:00
// Coerce actor into a [to, from, ...] array
2019-09-12 21:55:10 +02:00
const actors = [].concat(actor, actor);
notes.push(note);
messages.push({
from: actors[0],
to: actors[1],
message: message.text,
2020-06-17 11:54:24 +02:00
wrap: (message.wrap === undefined && autoWrap()) || !!message.wrap,
2019-09-12 21:55:10 +02:00
type: LINETYPE.NOTE,
2021-07-15 11:35:12 +02:00
placement: placement,
2019-09-12 21:55:10 +02:00
});
};
export const addLinks = function (actorId, text) {
// find the actor
const actor = getActor(actorId);
// JSON.parse the text
try {
let sanitizedText = sanitizeText(text.text, configApi.getConfig());
2021-10-14 21:08:42 +02:00
sanitizedText = sanitizedText.replace(/&amp;/g, '&');
sanitizedText = sanitizedText.replace(/&equals;/g, '=');
const links = JSON.parse(sanitizedText);
// add the deserialized text to the actor's links field.
insertLinks(actor, links);
} catch (e) {
log.error('error while parsing actor link text', e);
}
};
export const addALink = function (actorId, text) {
// find the actor
const actor = getActor(actorId);
try {
const links = {};
let sanitizedText = sanitizeText(text.text, configApi.getConfig());
var sep = sanitizedText.indexOf('@');
2021-10-14 21:08:42 +02:00
sanitizedText = sanitizedText.replace(/&amp;/g, '&');
sanitizedText = sanitizedText.replace(/&equals;/g, '=');
var label = sanitizedText.slice(0, sep - 1).trim();
var link = sanitizedText.slice(sep + 1).trim();
links[label] = link;
// add the deserialized text to the actor's links field.
insertLinks(actor, links);
} catch (e) {
log.error('error while parsing actor link text', e);
}
};
/**
* @param {any} actor
* @param {any} links
*/
function insertLinks(actor, links) {
if (actor.links == null) {
actor.links = links;
} else {
for (let key in links) {
actor.links[key] = links[key];
}
}
}
export const addProperties = function (actorId, text) {
// find the actor
const actor = getActor(actorId);
// JSON.parse the text
try {
let sanitizedText = sanitizeText(text.text, configApi.getConfig());
const properties = JSON.parse(sanitizedText);
// add the deserialized text to the actor's property field.
insertProperties(actor, properties);
} catch (e) {
log.error('error while parsing actor properties text', e);
}
};
/**
* @param {any} actor
* @param {any} properties
*/
function insertProperties(actor, properties) {
if (actor.properties == null) {
actor.properties = properties;
} else {
for (let key in properties) {
actor.properties[key] = properties[key];
}
}
}
export const addDetails = function (actorId, text) {
// find the actor
const actor = getActor(actorId);
const elem = document.getElementById(text.text);
// JSON.parse the text
try {
const text = elem.innerHTML;
const details = JSON.parse(text);
// add the deserialized text to the actor's property field.
if (details['properties']) {
insertProperties(actor, details['properties']);
}
if (details['links']) {
insertLinks(actor, details['links']);
}
} catch (e) {
log.error('error while parsing actor details text', e);
}
};
export const getActorProperty = function (actor, key) {
if (typeof actor !== 'undefined' && typeof actor.properties !== 'undefined') {
return actor.properties[key];
}
return undefined;
2021-09-14 23:26:43 +02:00
};
2021-07-15 11:35:12 +02:00
export const apply = function (param) {
2017-04-11 16:14:25 +02:00
if (param instanceof Array) {
2021-07-15 11:35:12 +02:00
param.forEach(function (item) {
2019-09-12 21:55:10 +02:00
apply(item);
});
2017-04-11 16:14:25 +02:00
} else {
switch (param.type) {
case 'sequenceIndex':
messages.push({
from: undefined,
to: undefined,
message: {
start: param.sequenceIndex,
step: param.sequenceIndexStep,
visible: param.sequenceVisible,
},
wrap: false,
type: param.signalType,
});
break;
case 'addParticipant':
addActor(param.actor, param.actor, param.description, 'participant');
break;
2017-04-11 16:14:25 +02:00
case 'addActor':
addActor(param.actor, param.actor, param.description, 'actor');
2019-09-12 21:55:10 +02:00
break;
2017-04-11 16:14:25 +02:00
case 'activeStart':
2019-09-12 21:55:10 +02:00
addSignal(param.actor, undefined, undefined, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'activeEnd':
2019-09-12 21:55:10 +02:00
addSignal(param.actor, undefined, undefined, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'addNote':
2019-09-12 21:55:10 +02:00
addNote(param.actor, param.placement, param.text);
break;
case 'addLinks':
addLinks(param.actor, param.text);
break;
case 'addALink':
addALink(param.actor, param.text);
break;
case 'addProperties':
addProperties(param.actor, param.text);
break;
case 'addDetails':
addDetails(param.actor, param.text);
break;
2017-04-11 16:14:25 +02:00
case 'addMessage':
2019-09-12 21:55:10 +02:00
addSignal(param.from, param.to, param.msg, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'loopStart':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, param.loopText, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'loopEnd':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, undefined, param.signalType);
break;
2019-07-23 07:47:49 +02:00
case 'rectStart':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, param.color, param.signalType);
break;
2019-07-23 07:47:49 +02:00
case 'rectEnd':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, undefined, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'optStart':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, param.optText, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'optEnd':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, undefined, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'altStart':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, param.altText, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'else':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, param.altText, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'altEnd':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, undefined, param.signalType);
break;
2022-05-17 20:23:45 +02:00
case 'setAccTitle':
setAccTitle(param.text);
2019-09-12 21:55:10 +02:00
break;
2017-04-11 16:14:25 +02:00
case 'parStart':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, param.parText, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'and':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, param.parText, param.signalType);
break;
2017-04-11 16:14:25 +02:00
case 'parEnd':
2019-09-12 21:55:10 +02:00
addSignal(undefined, undefined, undefined, param.signalType);
break;
case 'criticalStart':
addSignal(undefined, undefined, param.criticalText, param.signalType);
break;
case 'option':
addSignal(undefined, undefined, param.optionText, param.signalType);
break;
case 'criticalEnd':
addSignal(undefined, undefined, undefined, param.signalType);
break;
case 'breakStart':
addSignal(undefined, undefined, param.breakText, param.signalType);
break;
case 'breakEnd':
addSignal(undefined, undefined, undefined, param.signalType);
break;
}
2017-04-11 16:14:25 +02:00
}
2019-09-12 21:55:10 +02:00
};
2017-09-10 15:51:48 +02:00
export default {
addActor,
addMessage,
addSignal,
addLinks,
addDetails,
addProperties,
2020-06-17 11:54:24 +02:00
autoWrap,
setWrap,
enableSequenceNumbers,
disableSequenceNumbers,
showSequenceNumbers,
2017-09-10 15:51:48 +02:00
getMessages,
getActors,
getActor,
getActorKeys,
getActorProperty,
getAccTitle,
getDiagramTitle,
setDiagramTitle,
parseDirective,
getConfig: () => configApi.getConfig().sequence,
2017-09-10 15:51:48 +02:00
clear,
parseMessage,
2017-09-10 15:51:48 +02:00
LINETYPE,
ARROWTYPE,
PLACEMENT,
addNote,
2022-05-17 20:23:45 +02:00
setAccTitle,
2021-07-15 11:35:12 +02:00
apply,
setAccDescription,
getAccDescription,
2019-09-12 21:55:10 +02:00
};