Compare commits

..

25 Commits

Author SHA1 Message Date
shubhamparikh2704
fa28ec0bf9 updated config file 2025-08-22 19:16:25 +05:30
shubhamparikh2704
50d836ef8d updated config file 2025-08-22 19:11:27 +05:30
shubhamparikh2704
e8ca75c563 updated config file 2025-08-22 19:05:44 +05:30
shubhamparikh2704
a557447824 updated config file 2025-08-22 18:22:51 +05:30
shubhamparikh2704
a7cbc55d9c updated config file 2025-08-22 16:47:45 +05:30
shubhamparikh2704
4127689bf7 updated config file 2025-08-22 16:44:16 +05:30
shubhamparikh2704
feaa82e125 updated config file 2025-08-22 16:43:07 +05:30
shubhamparikh2704
e3779f2dce updated config file 2025-08-22 16:37:14 +05:30
shubhamparikh2704
45e0e439ba added config file 2025-08-22 16:27:01 +05:30
shubhamparikh2704
6bed51e19a updated workflow 2025-08-22 16:16:24 +05:30
shubhamparikh2704
7b619b1bd9 revert version 2025-08-22 16:09:59 +05:30
shubhamparikh2704
e7aead0cbe uddated cypress config 2025-08-22 16:03:53 +05:30
shubhamparikh2704
a4e26b1bc6 uddated sdk version 2025-08-22 16:01:00 +05:30
shubhamparikh2704
fc4945e297 updated workflow 2025-08-22 15:53:08 +05:30
shubhamparikh2704
7cee532741 updated file 2025-08-21 16:22:28 +05:30
shubhamparikh2704
a651665d4a updated workflow file 2025-08-21 15:49:47 +05:30
shubhamparikh2704
aff253c4ff updated workflow file 2025-08-21 15:41:45 +05:30
shubhamparikh2704
8c578c15da updated workflow file 2025-08-21 15:32:19 +05:30
shubhamparikh2704
af5256b7ed updated workflow file 2025-08-21 15:28:16 +05:30
shubhamparikh2704
6f50ba30a7 updated workflow file 2025-08-21 15:22:49 +05:30
shubhamparikh2704
2fabb4dbfc updated workflow file 2025-08-21 15:19:42 +05:30
Shubham P
bf2b5a2518 Update applitools-tests.yml 2025-08-21 15:15:33 +05:30
shubhamparikh2704
dbae731548 updated workflow file 2025-08-21 15:12:16 +05:30
shubhamparikh2704
9ba307429a updated workflow file 2025-08-21 15:10:40 +05:30
shubhamparikh2704
117d699027 added workflow file 2025-08-21 15:07:18 +05:30
30 changed files with 433 additions and 2367 deletions

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: Handle arrows correctly when auto number is enabled

View File

@@ -1,5 +0,0 @@
---
'mermaid': minor
---
feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`.

95
.github/workflows/applitools-tests.yml vendored Normal file
View File

@@ -0,0 +1,95 @@
name: Applitools E2E (Develop Branch) - Fixed
on:
push:
branches:
- develop
- applitools_workflow
workflow_dispatch:
# Manual triggering only - to limit Applitools usage
inputs:
parent_branch:
required: true
type: string
default: master
description: 'Parent branch to use for PRs'
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: read
env:
# on PRs from forks, this secret will always be empty, for security reasons
USE_APPLI: ${{ secrets.APPLITOOLS_API_KEY && 'true' || '' }}
jobs:
applitools-e2e:
runs-on: ubuntu-latest
container:
image: cypress/browsers:node-22.18.0-chrome-139.0.7258.127-1-ff-141.0.3-edge-139.0.3405.86-1
options: --user root --shm-size=2gb
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Check Applitools API Key
run: |
if [ -z "${{ secrets.APPLITOOLS_API_KEY }}" ]; then
echo "::error::APPLITOOLS_API_KEY secret is not set. Please add it to your repository secrets."
exit 1
else
echo "✅ Applitools API Key is present"
fi
- name: Setup Node.js and pnpm
run: |
# Install pnpm globally
npm install -g pnpm@10.4.1
# Verify installations
node --version
pnpm --version
- name: Setup Applitools Environment
run: |
# Set Applitools environment variables for proper CI integration
echo "APPLITOOLS_BATCH_ID=${{ github.run_id }}-${{ github.run_attempt }}" >> $GITHUB_ENV
echo "APPLITOOLS_BATCH_NAME=GitHub Actions - ${{ github.workflow }}" >> $GITHUB_ENV
echo "APPLITOOLS_SERVER_URL=https://eyes.applitools.com" >> $GITHUB_ENV
# Force disable local Eyes server
echo "APPLITOOLS_DISABLE_LOCAL_EYES_SERVER=true" >> $GITHUB_ENV
- name: Verify Cypress Installation
run: |
npx cypress verify
npx cypress info
- name: Run Cypress with Applitools (single spec)
uses: cypress-io/github-action@v6
with:
command: pnpm cypress
start: pnpm dev
wait-on: http://localhost:9000
wait-on-timeout: 180
browser: chrome
headless: true
env:
# Ensure these are visible to Cypress + Applitools
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
APPLITOOLS_BATCH_ID: ${{ env.APPLITOOLS_BATCH_ID }}
APPLITOOLS_BATCH_NAME: ${{ env.APPLITOOLS_BATCH_NAME }}
APPLITOOLS_SERVER_URL: ${{ env.APPLITOOLS_SERVER_URL }}
APPLITOOLS_DISABLE_LOCAL_EYES_SERVER: true
USE_APPLI: true
# Force Applitools to use cloud service instead of local server
APPLITOOLS_DONT_CLOSE_BATCHES: false
APPLITOOLS_SAVE_DEBUG_SCREENSHOTS: false
# Disable any local server connections
APPLITOOLS_PROXY_URL: ''
# GitHub Actions CI environment
CI: true
# Disable Chrome sandbox for container
ELECTRON_EXTRA_LAUNCH_ARGS: '--disable-dev-shm-usage'

View File

@@ -58,7 +58,7 @@ jobs:
echo "EOF" >> $GITHUB_OUTPUT
- name: Commit and create pull request
uses: peter-evans/create-pull-request@18e469570b1cf0dfc11d60ec121099f8ff3e617a
uses: peter-evans/create-pull-request@cb4d3bfce175d44325c6b7697f81e0afe8a79bdf
with:
add-paths: |
cypress/timings.json

38
appli.config.ts Normal file
View File

@@ -0,0 +1,38 @@
export default {
// Explicitly set the server URL to use Applitools cloud service
serverUrl: 'https://eyes.applitools.com',
// API key from environment variable
apiKey: process.env.APPLITOOLS_API_KEY,
// Batch configuration
batch: {
name: 'Cypress Tests',
id: process.env.APPLITOOLS_BATCH_ID,
},
// Browser configuration for CI
browser: [{ name: 'chrome', width: 1440, height: 1024 }],
// Test concurrency (reduce for stability in CI)
testConcurrency: 1,
// Viewport size
viewportSize: { width: 1440, height: 1024 },
// Force full page screenshots
forceFullPageScreenshot: true,
// Don't fail tests on visual differences (optional)
exitcode: false,
// Additional settings for CI stability
matchTimeout: 2000,
// Disable local Eyes server
// cspell:ignore dont
dontCloseBatches: false,
// Save debug screenshots on failure
saveDebugScreenshots: process.env.CI ? false : true,
} as const;

View File

@@ -1,42 +1,90 @@
import eyesPlugin from '@applitools/eyes-cypress';
// cypress.config.ts
import { defineConfig } from 'cypress';
import { registerArgosTask } from '@argos-ci/cypress/task';
import coverage from '@cypress/code-coverage/task.js';
import { defineConfig } from 'cypress';
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin.js';
import cypressSplit from 'cypress-split';
import eyesPlugin from '@applitools/eyes-cypress';
export default eyesPlugin(
defineConfig({
projectId: 'n2sma2',
viewportWidth: 1440,
viewportHeight: 1024,
e2e: {
specPattern: 'cypress/integration/**/*.{js,ts}',
setupNodeEvents(on, config) {
coverage(on, config);
cypressSplit(on, config);
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1');
}
return launchOptions;
});
// copy any needed variables from process.env to config.env
config.env.useAppli = process.env.USE_APPLI ? true : false;
config.env.useArgos = process.env.RUN_VISUAL_TEST === 'true';
// --- Base Cypress config ---
const baseConfig = defineConfig({
projectId: 'n2sma2',
viewportWidth: 1440,
viewportHeight: 1024,
e2e: {
specPattern: 'cypress/integration/**/*.{js,ts}',
setupNodeEvents(on, config) {
// Code coverage
coverage(on, config);
if (config.env.useArgos) {
registerArgosTask(on, config, {
// Enable upload to Argos only when it runs on CI.
uploadToArgos: !!process.env.CI,
});
} else {
addMatchImageSnapshotPlugin(on, config);
// Test splitting
cypressSplit(on, config);
// Browser tweaks for CI
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push(
'--window-size=1440,1024',
'--force-device-scale-factor=1',
'--no-sandbox',
'--disable-dev-shm-usage',
'--disable-gpu',
'--disable-web-security'
);
}
// do not forget to return the changed config object!
return config;
},
return launchOptions;
});
// Env flags
config.env.useAppli = process.env.USE_APPLI === 'true';
config.env.useArgos = process.env.RUN_VISUAL_TEST === 'true';
if (config.env.useArgos) {
registerArgosTask(on, config, { uploadToArgos: !!process.env.CI });
} else {
addMatchImageSnapshotPlugin(on, config);
}
return config;
},
video: false,
})
);
},
video: false,
defaultCommandTimeout: 10000,
requestTimeout: 10000,
responseTimeout: 10000,
pageLoadTimeout: 30000,
});
// --- Conditional Applitools wrapper ---
function withApplitools(config: Cypress.ConfigOptions): Cypress.ConfigOptions {
const shouldLoadApplitools = !!process.env.APPLITOOLS_API_KEY && process.env.USE_APPLI === 'true';
if (shouldLoadApplitools) {
return eyesPlugin(config, {
serverUrl: 'https://eyes.applitools.com',
batch: {
name:
process.env.APPLITOOLS_BATCH_NAME ||
`GitHub Actions - ${process.env.GITHUB_WORKFLOW || 'Cypress Tests'}`,
id:
process.env.APPLITOOLS_BATCH_ID ||
`${process.env.GITHUB_RUN_ID}-${process.env.GITHUB_RUN_ATTEMPT}`,
},
testConcurrency: 1,
browser: { name: 'chrome', width: 1440, height: 1024 },
viewportSize: { width: 1440, height: 1024 },
matchTimeout: 2000,
forceFullPageScreenshot: true,
// cspell:ignore dont
dontCloseBatches: false,
saveDebugScreenshots: false,
saveDiffs: false,
concurrency: 1,
});
}
return config;
}
// --- Export final config ---
export default withApplitools(baseConfig);

View File

@@ -1,659 +0,0 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
const looks = ['classic'];
const participantTypes = [
{ type: 'participant', display: 'participant' },
{ type: 'actor', display: 'actor' },
{ type: 'boundary', display: 'boundary' },
{ type: 'control', display: 'control' },
{ type: 'entity', display: 'entity' },
{ type: 'database', display: 'database' },
{ type: 'collections', display: 'collections' },
{ type: 'queue', display: 'queue' },
];
const restrictedTypes = ['boundary', 'control', 'entity', 'database', 'collections', 'queue'];
const interactionTypes = ['->>', '-->>', '->', '-->', '-x', '--x', '->>+', '-->>+'];
const notePositions = ['left of', 'right of', 'over'];
function getParticipantLine(name, type, alias) {
if (restrictedTypes.includes(type)) {
return ` participant ${name}@{ "type" : "${type}" }\n`;
} else if (alias) {
return ` participant ${name}@{ "type" : "${type}" } \n`;
} else {
return ` participant ${name}@{ "type" : "${type}" }\n`;
}
}
looks.forEach((look) => {
describe(`Sequence Diagram Tests - ${look} look`, () => {
it('should render all participant types', () => {
let diagramCode = `sequenceDiagram\n`;
participantTypes.forEach((pt, index) => {
const name = `${pt.display}${index}`;
diagramCode += getParticipantLine(name, pt.type);
});
for (let i = 0; i < participantTypes.length - 1; i++) {
diagramCode += ` ${participantTypes[i].display}${i} ->> ${participantTypes[i + 1].display}${i + 1}: Message ${i}\n`;
}
imgSnapshotTest(diagramCode, { look, sequence: { diagramMarginX: 50, diagramMarginY: 10 } });
});
it('should render all interaction types', () => {
let diagramCode = `sequenceDiagram\n`;
diagramCode += getParticipantLine('A', 'actor');
diagramCode += getParticipantLine('B', 'boundary');
interactionTypes.forEach((interaction, index) => {
diagramCode += ` A ${interaction} B: ${interaction} message ${index}\n`;
});
imgSnapshotTest(diagramCode, { look });
});
it('should render participant creation and destruction', () => {
let diagramCode = `sequenceDiagram\n`;
participantTypes.forEach((pt, index) => {
const name = `${pt.display}${index}`;
diagramCode += getParticipantLine('A', pt.type);
diagramCode += getParticipantLine('B', pt.type);
diagramCode += ` create participant ${name}@{ "type" : "${pt.type}" }\n`;
diagramCode += ` A ->> ${name}: Hello ${pt.display}\n`;
if (index % 2 === 0) {
diagramCode += ` destroy ${name}\n`;
}
});
imgSnapshotTest(diagramCode, { look });
});
it('should render notes in all positions', () => {
let diagramCode = `sequenceDiagram\n`;
diagramCode += getParticipantLine('A', 'actor');
diagramCode += getParticipantLine('B', 'boundary');
notePositions.forEach((position, index) => {
diagramCode += ` Note ${position} A: Note ${position} ${index}\n`;
});
diagramCode += ` A ->> B: Message with notes\n`;
imgSnapshotTest(diagramCode, { look });
});
it('should render parallel interactions', () => {
let diagramCode = `sequenceDiagram\n`;
participantTypes.slice(0, 4).forEach((pt, index) => {
diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type);
});
diagramCode += ` par Parallel actions\n`;
for (let i = 0; i < 3; i += 2) {
diagramCode += ` ${participantTypes[i].display}${i} ->> ${participantTypes[i + 1].display}${i + 1}: Message ${i}\n`;
if (i < participantTypes.length - 2) {
diagramCode += ` and\n`;
}
}
diagramCode += ` end\n`;
imgSnapshotTest(diagramCode, { look });
});
it('should render alternative flows', () => {
let diagramCode = `sequenceDiagram\n`;
diagramCode += getParticipantLine('A', 'actor');
diagramCode += getParticipantLine('B', 'boundary');
diagramCode += ` alt Successful case\n`;
diagramCode += ` A ->> B: Request\n`;
diagramCode += ` B -->> A: Success\n`;
diagramCode += ` else Failure case\n`;
diagramCode += ` A ->> B: Request\n`;
diagramCode += ` B --x A: Failure\n`;
diagramCode += ` end\n`;
imgSnapshotTest(diagramCode, { look });
});
it('should render loops', () => {
let diagramCode = `sequenceDiagram\n`;
participantTypes.slice(0, 3).forEach((pt, index) => {
diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type);
});
diagramCode += ` loop For each participant\n`;
for (let i = 0; i < 3; i++) {
diagramCode += ` ${participantTypes[0].display}0 ->> ${participantTypes[1].display}1: Message ${i}\n`;
}
diagramCode += ` end\n`;
imgSnapshotTest(diagramCode, { look });
});
it('should render boxes around groups', () => {
let diagramCode = `sequenceDiagram\n`;
diagramCode += ` box Group 1\n`;
participantTypes.slice(0, 3).forEach((pt, index) => {
diagramCode += ` ${getParticipantLine(`${pt.display}${index}`, pt.type)}`;
});
diagramCode += ` end\n`;
diagramCode += ` box rgb(200,220,255) Group 2\n`;
participantTypes.slice(3, 6).forEach((pt, index) => {
diagramCode += ` ${getParticipantLine(`${pt.display}${index}`, pt.type)}`;
});
diagramCode += ` end\n`;
diagramCode += ` ${participantTypes[0].display}0 ->> ${participantTypes[3].display}0: Cross-group message\n`;
imgSnapshotTest(diagramCode, { look });
});
it('should render with different font settings', () => {
let diagramCode = `sequenceDiagram\n`;
participantTypes.slice(0, 3).forEach((pt, index) => {
diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type);
});
diagramCode += ` ${participantTypes[0].display}0 ->> ${participantTypes[1].display}1: Regular message\n`;
diagramCode += ` Note right of ${participantTypes[1].display}1: Regular note\n`;
imgSnapshotTest(diagramCode, {
look,
sequence: {
actorFontFamily: 'courier',
actorFontSize: 14,
messageFontFamily: 'Arial',
messageFontSize: 12,
noteFontFamily: 'times',
noteFontSize: 16,
noteAlign: 'left',
},
});
});
});
});
// Additional tests for specific combinations
describe('Sequence Diagram Special Cases', () => {
it('should render complex sequence with all features', () => {
const diagramCode = `
sequenceDiagram
box rgb(200,220,255) Authentication
actor User
participant LoginUI@{ "type": "boundary" }
participant AuthService@{ "type": "control" }
participant UserDB@{ "type": "database" }
end
box rgb(200,255,220) Order Processing
participant Order@{ "type": "entity" }
participant OrderQueue@{ "type": "queue" }
participant AuditLogs@{ "type": "collections" }
end
User ->> LoginUI: Enter credentials
LoginUI ->> AuthService: Validate
AuthService ->> UserDB: Query user
UserDB -->> AuthService: User data
alt Valid credentials
AuthService -->> LoginUI: Success
LoginUI -->> User: Welcome
par Place order
User ->> Order: New order
Order ->> OrderQueue: Process
and
Order ->> AuditLogs: Record
end
loop Until confirmed
OrderQueue ->> Order: Update status
Order -->> User: Notification
end
else Invalid credentials
AuthService --x LoginUI: Failure
LoginUI --x User: Retry
end
`;
imgSnapshotTest(diagramCode, {});
});
it('should render with wrapped messages and notes', () => {
const diagramCode = `
sequenceDiagram
participant A
participant B
A ->> B: This is a very long message that should wrap properly in the diagram rendering
Note over A,B: This is a very long note that should also wrap properly when rendered in the diagram
par Wrapped parallel
A ->> B: Parallel message 1<br>with explicit line break
and
B ->> A: Parallel message 2<br>with explicit line break
end
loop Wrapped loop
Note right of B: This is a long note<br>in a loop
A ->> B: Message in loop
end
`;
imgSnapshotTest(diagramCode, { sequence: { wrap: true } });
});
describe('Sequence Diagram Rendering with Different Participant Types', () => {
it('should render a sequence diagram with various participant types', () => {
imgSnapshotTest(
`
sequenceDiagram
participant User@{ "type": "actor" }
participant AuthService@{ "type": "control" }
participant UI@{ "type": "boundary" }
participant OrderController@{ "type": "control" }
participant Product@{ "type": "entity" }
participant MongoDB@{ "type": "database" }
participant Products@{ "type": "collections" }
participant OrderQueue@{ "type": "queue" }
User ->> UI: Login request
UI ->> AuthService: Validate credentials
AuthService -->> UI: Authentication token
UI ->> OrderController: Place order
OrderController ->> Product: Check availability
Product -->> OrderController: Available
OrderController ->> MongoDB: Save order
MongoDB -->> OrderController: Order saved
OrderController ->> OrderQueue: Process payment
OrderQueue -->> User: Order confirmation
`
);
});
it('should render participant creation and destruction with different types', () => {
imgSnapshotTest(`
sequenceDiagram
participant Alice@{ "type" : "boundary" }
Alice->>Bob: Hello Bob, how are you ?
Bob->>Alice: Fine, thank you. And you?
create participant Carl@{ "type" : "control" }
Alice->>Carl: Hi Carl!
create actor D as Donald
Carl->>D: Hi!
destroy Carl
Alice-xCarl: We are too many
destroy Bob
Bob->>Alice: I agree
`);
});
it('should handle complex interactions between different participant types', () => {
imgSnapshotTest(
`
sequenceDiagram
box rgb(200,220,255) Authentication
participant User@{ "type": "actor" }
participant LoginUI@{ "type": "boundary" }
participant AuthService@{ "type": "control" }
participant UserDB@{ "type": "database" }
end
box rgb(200,255,220) Order Processing
participant Order@{ "type": "entity" }
participant OrderQueue@{ "type": "queue" }
participant AuditLogs@{ "type": "collections" }
end
User ->> LoginUI: Enter credentials
LoginUI ->> AuthService: Validate
AuthService ->> UserDB: Query user
UserDB -->> AuthService: User data
alt Valid credentials
AuthService -->> LoginUI: Success
LoginUI -->> User: Welcome
par Place order
User ->> Order: New order
Order ->> OrderQueue: Process
and
Order ->> AuditLogs: Record
end
loop Until confirmed
OrderQueue ->> Order: Update status
Order -->> User: Notification
end
else Invalid credentials
AuthService --x LoginUI: Failure
LoginUI --x User: Retry
end
`,
{ sequence: { useMaxWidth: false } }
);
});
it('should render parallel processes with different participant types', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Customer@{ "type": "actor" }
participant Frontend@{ "type": "participant" }
participant PaymentService@{ "type": "boundary" }
participant InventoryManager@{ "type": "control" }
participant Order@{ "type": "entity" }
participant OrdersDB@{ "type": "database" }
participant NotificationQueue@{ "type": "queue" }
Customer ->> Frontend: Place order
Frontend ->> Order: Create order
par Parallel Processing
Order ->> PaymentService: Process payment
and
Order ->> InventoryManager: Reserve items
end
PaymentService -->> Order: Payment confirmed
InventoryManager -->> Order: Items reserved
Order ->> OrdersDB: Save finalized order
OrdersDB -->> Order: Order saved
Order ->> NotificationQueue: Send confirmation
NotificationQueue -->> Customer: Order confirmation
`
);
});
});
it('should render different participant types with notes and loops', () => {
imgSnapshotTest(
`
sequenceDiagram
actor Admin
participant Dashboard
participant AuthService@{ "type" : "boundary" }
participant UserManager@{ "type" : "control" }
participant UserProfile@{ "type" : "entity" }
participant UserDB@{ "type" : "database" }
participant Logs@{ "type" : "database" }
Admin ->> Dashboard: Open user management
loop Authentication check
Dashboard ->> AuthService: Verify admin rights
AuthService ->> Dashboard: Access granted
end
Dashboard ->> UserManager: List users
UserManager ->> UserDB: Query users
UserDB ->> UserManager: Return user data
Note right of UserDB: Encrypted data<br/>requires decryption
UserManager ->> UserProfile: Format profiles
UserProfile ->> UserManager: Formatted data
UserManager ->> Dashboard: Display users
Dashboard ->> Logs: Record access
Logs ->> Admin: Audit trail
`
);
});
it('should render different participant types with alternative flows', () => {
imgSnapshotTest(
`
sequenceDiagram
actor Client
participant MobileApp
participant CloudService@{ "type" : "boundary" }
participant DataProcessor@{ "type" : "control" }
participant Transaction@{ "type" : "entity" }
participant TransactionsDB@{ "type" : "database" }
participant EventBus@{ "type" : "queue" }
Client ->> MobileApp: Initiate transaction
MobileApp ->> CloudService: Authenticate
alt Authentication successful
CloudService -->> MobileApp: Auth token
MobileApp ->> DataProcessor: Process data
DataProcessor ->> Transaction: Create transaction
Transaction ->> TransactionsDB: Save record
TransactionsDB -->> Transaction: Confirmation
Transaction ->> EventBus: Publish event
EventBus -->> Client: Notification
else Authentication failed
CloudService -->> MobileApp: Error
MobileApp -->> Client: Show error
end
`
);
});
it('should render different participant types with wrapping text', () => {
imgSnapshotTest(
`
sequenceDiagram
participant B@{ "type" : "boundary" }
participant C@{ "type" : "control" }
participant E@{ "type" : "entity" }
participant DB@{ "type" : "database" }
participant COL@{ "type" : "collections" }
participant Q@{ "type" : "queue" }
FE ->> B: Another long message<br/>with explicit<br/>line breaks
B -->> FE: Response message that is also quite long and needs to wrap
FE ->> C: Process data
C ->> E: Validate
E -->> C: Validation result
C ->> DB: Save
DB -->> C: Save result
C ->> COL: Log
COL -->> Q: Forward
Q -->> LongNameUser: Final response with confirmation of all actions taken
`,
{ sequence: { wrap: true } }
);
});
describe('Sequence Diagram - New Participant Types with Long Notes and Messages', () => {
it('should render long notes left of boundary', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice@{ "type" : "boundary" }
actor Bob
Alice->>Bob: Hola
Note left of Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
Bob->>Alice: I'm short though
`,
{}
);
});
it('should render wrapped long notes left of control', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice@{ "type" : "control" }
actor Bob
Alice->>Bob: Hola
Note left of Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
Bob->>Alice: I'm short though
`,
{}
);
});
it('should render long notes right of entity', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice@{ "type" : "entity" }
actor Bob
Alice->>Bob: Hola
Note right of Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
Bob->>Alice: I'm short though
`,
{}
);
});
it('should render wrapped long notes right of database', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice@{ "type" : "database" }
actor Bob
Alice->>Bob: Hola
Note right of Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
Bob->>Alice: I'm short though
`,
{}
);
});
it('should render long notes over collections', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice@{ "type" : "collections" }
actor Bob
Alice->>Bob: Hola
Note over Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
Bob->>Alice: I'm short though
`,
{}
);
});
it('should render wrapped long notes over queue', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice@{ "type" : "queue" }
actor Bob
Alice->>Bob: Hola
Note over Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
Bob->>Alice: I'm short though
`,
{}
);
});
it('should render notes over actor and boundary', () => {
imgSnapshotTest(
`
sequenceDiagram
actor Alice
participant Charlie@{ "type" : "boundary" }
note over Alice: Some note
note over Charlie: Other note
`,
{}
);
});
it('should render long messages from database to collections', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice@{ "type" : "database" }
participant Bob@{ "type" : "collections" }
Alice->>Bob: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
Bob->>Alice: I'm short though
`,
{}
);
});
it('should render wrapped long messages from control to entity', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice@{ "type" : "control" }
participant Bob@{ "type" : "entity" }
Alice->>Bob:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
Bob->>Alice: I'm short though
`,
{}
);
});
it('should render long messages from queue to boundary', () => {
imgSnapshotTest(
`
sequenceDiagram
participant Alice@{ "type" : "queue" }
participant Bob@{ "type" : "boundary" }
Alice->>Bob: I'm short
Bob->>Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
`,
{}
);
});
it('should render wrapped long messages from actor to database', () => {
imgSnapshotTest(
`
sequenceDiagram
actor Alice
participant Bob@{ "type" : "database" }
Alice->>Bob: I'm short
Bob->>Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
`,
{}
);
});
});
describe('svg size', () => {
it('should render a sequence diagram when useMaxWidth is true (default)', () => {
renderGraph(
`
sequenceDiagram
actor Alice
participant Bob@{ "type" : "boundary" }
participant John@{ "type" : "control" }
Alice ->> Bob: Hello Bob, how are you?
Bob-->>John: How about you John?
Bob--x Alice: I am good thanks!
Bob-x John: I am good thanks!
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
Bob-->Alice: Checking with John...
alt either this
Alice->>John: Yes
else or this
Alice->>John: No
else or this will happen
Alice->John: Maybe
end
par this happens in parallel
Alice -->> Bob: Parallel message 1
and
Alice -->> John: Parallel message 2
end
`,
{ sequence: { useMaxWidth: true } }
);
cy.get('svg').should((svg) => {
expect(svg).to.have.attr('width', '100%');
const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(820 * 0.95, 820 * 1.05);
});
});
it('should render a sequence diagram when useMaxWidth is false', () => {
renderGraph(
`
sequenceDiagram
actor Alice
participant Bob@{ "type" : "boundary" }
participant John@{ "type" : "control" }
Alice ->> Bob: Hello Bob, how are you?
Bob-->>John: How about you John?
Bob--x Alice: I am good thanks!
Bob-x John: I am good thanks!
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
Bob-->Alice: Checking with John...
alt either this
Alice->>John: Yes
else or this
Alice->>John: No
else or this will happen
Alice->John: Maybe
end
par this happens in parallel
Alice -->> Bob: Parallel message 1
and
Alice -->> John: Parallel message 2
end
`,
{ sequence: { useMaxWidth: false } }
);
cy.get('svg').should((svg) => {
const width = parseFloat(svg.attr('width'));
expect(width).to.be.within(820 * 0.95, 820 * 1.05);
expect(svg).to.not.have.attr('style');
});
});
});
});

View File

@@ -893,17 +893,6 @@ describe('Sequence diagram', () => {
}
);
});
it('should handle bidirectional arrows with autonumber', () => {
imgSnapshotTest(`
sequenceDiagram
autonumber
participant A
participant B
A<<->>B: This is a bidirectional message
A->B: This is a normal message`);
});
it('should support actor links and properties when not mirrored EXPERIMENTAL: USE WITH CAUTION', () => {
//Be aware that the syntax for "properties" is likely to be changed.
imgSnapshotTest(

View File

@@ -2,223 +2,219 @@
"durations": [
{
"spec": "cypress/integration/other/configuration.spec.js",
"duration": 6162
"duration": 6297
},
{
"spec": "cypress/integration/other/external-diagrams.spec.js",
"duration": 2148
"duration": 2187
},
{
"spec": "cypress/integration/other/ghsa.spec.js",
"duration": 3585
"duration": 3509
},
{
"spec": "cypress/integration/other/iife.spec.js",
"duration": 2099
"duration": 2218
},
{
"spec": "cypress/integration/other/interaction.spec.js",
"duration": 12119
"duration": 12104
},
{
"spec": "cypress/integration/other/rerender.spec.js",
"duration": 2063
"duration": 2151
},
{
"spec": "cypress/integration/other/xss.spec.js",
"duration": 31921
"duration": 33064
},
{
"spec": "cypress/integration/rendering/appli.spec.js",
"duration": 3385
"duration": 3488
},
{
"spec": "cypress/integration/rendering/architecture.spec.ts",
"duration": 108
"duration": 106
},
{
"spec": "cypress/integration/rendering/block.spec.js",
"duration": 18063
"duration": 18317
},
{
"spec": "cypress/integration/rendering/c4.spec.js",
"duration": 5519
"duration": 5592
},
{
"spec": "cypress/integration/rendering/classDiagram-elk-v3.spec.js",
"duration": 40040
"duration": 39358
},
{
"spec": "cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js",
"duration": 38665
"duration": 37160
},
{
"spec": "cypress/integration/rendering/classDiagram-v2.spec.js",
"duration": 22836
"duration": 23660
},
{
"spec": "cypress/integration/rendering/classDiagram-v3.spec.js",
"duration": 37096
"duration": 36866
},
{
"spec": "cypress/integration/rendering/classDiagram.spec.js",
"duration": 16452
"duration": 17334
},
{
"spec": "cypress/integration/rendering/conf-and-directives.spec.js",
"duration": 10387
"duration": 9871
},
{
"spec": "cypress/integration/rendering/current.spec.js",
"duration": 2803
"duration": 2833
},
{
"spec": "cypress/integration/rendering/erDiagram-unified.spec.js",
"duration": 86891
"duration": 85321
},
{
"spec": "cypress/integration/rendering/erDiagram.spec.js",
"duration": 15206
"duration": 15673
},
{
"spec": "cypress/integration/rendering/errorDiagram.spec.js",
"duration": 3540
"duration": 3724
},
{
"spec": "cypress/integration/rendering/flowchart-elk.spec.js",
"duration": 41975
"duration": 41178
},
{
"spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js",
"duration": 30909
"duration": 29966
},
{
"spec": "cypress/integration/rendering/flowchart-icon.spec.js",
"duration": 7881
"duration": 7689
},
{
"spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts",
"duration": 24294
"duration": 24709
},
{
"spec": "cypress/integration/rendering/flowchart-v2.spec.js",
"duration": 47652
"duration": 45565
},
{
"spec": "cypress/integration/rendering/flowchart.spec.js",
"duration": 32049
"duration": 31144
},
{
"spec": "cypress/integration/rendering/gantt.spec.js",
"duration": 20248
"duration": 20808
},
{
"spec": "cypress/integration/rendering/gitGraph.spec.js",
"duration": 51202
"duration": 49985
},
{
"spec": "cypress/integration/rendering/iconShape.spec.ts",
"duration": 283546
"duration": 273272
},
{
"spec": "cypress/integration/rendering/imageShape.spec.ts",
"duration": 57257
"duration": 55880
},
{
"spec": "cypress/integration/rendering/info.spec.ts",
"duration": 3352
"duration": 3271
},
{
"spec": "cypress/integration/rendering/journey.spec.js",
"duration": 7423
"duration": 7293
},
{
"spec": "cypress/integration/rendering/kanban.spec.ts",
"duration": 7804
"duration": 7861
},
{
"spec": "cypress/integration/rendering/katex.spec.js",
"duration": 3847
"duration": 3922
},
{
"spec": "cypress/integration/rendering/marker_unique_id.spec.js",
"duration": 2637
"duration": 2726
},
{
"spec": "cypress/integration/rendering/mindmap.spec.ts",
"duration": 11658
"duration": 11670
},
{
"spec": "cypress/integration/rendering/newShapes.spec.ts",
"duration": 149500
"duration": 146020
},
{
"spec": "cypress/integration/rendering/oldShapes.spec.ts",
"duration": 115427
"duration": 114244
},
{
"spec": "cypress/integration/rendering/packet.spec.ts",
"duration": 4801
"duration": 5036
},
{
"spec": "cypress/integration/rendering/pie.spec.ts",
"duration": 6786
"duration": 6545
},
{
"spec": "cypress/integration/rendering/quadrantChart.spec.js",
"duration": 9422
"duration": 9097
},
{
"spec": "cypress/integration/rendering/radar.spec.js",
"duration": 5652
"duration": 5676
},
{
"spec": "cypress/integration/rendering/requirement.spec.js",
"duration": 2787
"duration": 2795
},
{
"spec": "cypress/integration/rendering/requirementDiagram-unified.spec.js",
"duration": 53631
"duration": 51660
},
{
"spec": "cypress/integration/rendering/sankey.spec.ts",
"duration": 7075
},
{
"spec": "cypress/integration/rendering/sequencediagram-v2.spec.js",
"duration": 20446
"duration": 6957
},
{
"spec": "cypress/integration/rendering/sequencediagram.spec.js",
"duration": 37326
"duration": 36026
},
{
"spec": "cypress/integration/rendering/stateDiagram-v2.spec.js",
"duration": 29208
"duration": 29551
},
{
"spec": "cypress/integration/rendering/stateDiagram.spec.js",
"duration": 16328
"duration": 17364
},
{
"spec": "cypress/integration/rendering/theme.spec.js",
"duration": 30541
"duration": 30209
},
{
"spec": "cypress/integration/rendering/timeline.spec.ts",
"duration": 8611
"duration": 8699
},
{
"spec": "cypress/integration/rendering/treemap.spec.ts",
"duration": 11878
"duration": 12168
},
{
"spec": "cypress/integration/rendering/xyChart.spec.js",
"duration": 20400
"duration": 21453
},
{
"spec": "cypress/integration/rendering/zenuml.spec.js",
"duration": 3528
"duration": 3577
}
]
}

View File

@@ -19,7 +19,6 @@
- [addDirective](functions/addDirective.md)
- [getConfig](functions/getConfig.md)
- [getSiteConfig](functions/getSiteConfig.md)
- [getUserDefinedConfig](functions/getUserDefinedConfig.md)
- [reset](functions/reset.md)
- [sanitize](functions/sanitize.md)
- [saveConfigFromInitialize](functions/saveConfigFromInitialize.md)

View File

@@ -1,19 +0,0 @@
> **Warning**
>
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
>
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md](../../../../../packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md).
[**mermaid**](../../README.md)
---
# Function: getUserDefinedConfig()
> **getUserDefinedConfig**(): [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md)
Defined in: [packages/mermaid/src/config.ts:252](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L252)
## Returns
[`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md)

View File

@@ -10,7 +10,7 @@
# Interface: ParseOptions
Defined in: [packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L84)
Defined in: [packages/mermaid/src/types.ts:72](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L72)
## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mer
> `optional` **suppressErrors**: `boolean`
Defined in: [packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89)
Defined in: [packages/mermaid/src/types.ts:77](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L77)
If `true`, parse will return `false` instead of throwing error when the diagram is invalid.
The `parseError` function will not be called.

View File

@@ -10,7 +10,7 @@
# Interface: ParseResult
Defined in: [packages/mermaid/src/types.ts:92](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L92)
Defined in: [packages/mermaid/src/types.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L80)
## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:92](https://github.com/mermaid-js/mer
> **config**: [`MermaidConfig`](MermaidConfig.md)
Defined in: [packages/mermaid/src/types.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L100)
Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88)
The config passed as YAML frontmatter or directives
@@ -28,6 +28,6 @@ The config passed as YAML frontmatter or directives
> **diagramType**: `string`
Defined in: [packages/mermaid/src/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L96)
Defined in: [packages/mermaid/src/types.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L84)
The diagram type, e.g. 'flowchart', 'sequence', etc.

View File

@@ -10,7 +10,7 @@
# Interface: RenderResult
Defined in: [packages/mermaid/src/types.ts:110](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L110)
Defined in: [packages/mermaid/src/types.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L98)
## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:110](https://github.com/mermaid-js/me
> `optional` **bindFunctions**: (`element`) => `void`
Defined in: [packages/mermaid/src/types.ts:128](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L128)
Defined in: [packages/mermaid/src/types.ts:116](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L116)
Bind function to be called after the svg has been inserted into the DOM.
This is necessary for adding event listeners to the elements in the svg.
@@ -45,7 +45,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
> **diagramType**: `string`
Defined in: [packages/mermaid/src/types.ts:118](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L118)
Defined in: [packages/mermaid/src/types.ts:106](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L106)
The diagram type, e.g. 'flowchart', 'sequence', etc.
@@ -55,6 +55,6 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
> **svg**: `string`
Defined in: [packages/mermaid/src/types.ts:114](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L114)
Defined in: [packages/mermaid/src/types.ts:102](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L102)
The svg code for the rendered graph.

View File

@@ -983,23 +983,11 @@ flowchart TD
- `b`
- **w**: The width of the image. If not defined, this will default to the natural width of the image.
- **h**: The height of the image. If not defined, this will default to the natural height of the image.
- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the width (`w`) accordingly to the height (`h`). If not defined, this will default to `off` Possible values are:
- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the height (`h`) accordingly to the width (`w`). If not defined, this will default to `off` Possible values are:
- `on`
- `off`
If you want to resize an image, but keep the same aspect ratio, set `h`, and set `constraint: on` to constrain the aspect ratio. E.g.
```mermaid-example
flowchart TD
%% My image with a constrained aspect ratio
A@{ img: "https://mermaid.js.org/favicon.svg", label: "My example image label", pos: "t", h: 60, constraint: "on" }
```
```mermaid
flowchart TD
%% My image with a constrained aspect ratio
A@{ img: "https://mermaid.js.org/favicon.svg", label: "My example image label", pos: "t", h: 60, constraint: "on" }
```
These new shapes provide additional flexibility and visual appeal to your flowcharts, making them more informative and engaging.
## Links between nodes

View File

@@ -74,126 +74,6 @@ sequenceDiagram
Bob->>Alice: Hi Alice
```
### Boundary
If you want to use the boundary symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "boundary" }
participant Bob
Alice->>Bob: Request from boundary
Bob->>Alice: Response to boundary
```
```mermaid
sequenceDiagram
participant Alice@{ "type" : "boundary" }
participant Bob
Alice->>Bob: Request from boundary
Bob->>Alice: Response to boundary
```
### Control
If you want to use the control symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "control" }
participant Bob
Alice->>Bob: Control request
Bob->>Alice: Control response
```
```mermaid
sequenceDiagram
participant Alice@{ "type" : "control" }
participant Bob
Alice->>Bob: Control request
Bob->>Alice: Control response
```
### Entity
If you want to use the entity symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "entity" }
participant Bob
Alice->>Bob: Entity request
Bob->>Alice: Entity response
```
```mermaid
sequenceDiagram
participant Alice@{ "type" : "entity" }
participant Bob
Alice->>Bob: Entity request
Bob->>Alice: Entity response
```
### Database
If you want to use the database symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "database" }
participant Bob
Alice->>Bob: DB query
Bob->>Alice: DB result
```
```mermaid
sequenceDiagram
participant Alice@{ "type" : "database" }
participant Bob
Alice->>Bob: DB query
Bob->>Alice: DB result
```
### Collections
If you want to use the collections symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "collections" }
participant Bob
Alice->>Bob: Collections request
Bob->>Alice: Collections response
```
```mermaid
sequenceDiagram
participant Alice@{ "type" : "collections" }
participant Bob
Alice->>Bob: Collections request
Bob->>Alice: Collections response
```
### Queue
If you want to use the queue symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "queue" }
participant Bob
Alice->>Bob: Queue message
Bob->>Alice: Queue response
```
```mermaid
sequenceDiagram
participant Alice@{ "type" : "queue" }
participant Bob
Alice->>Bob: Queue message
Bob->>Alice: Queue response
```
### Aliases
The actor can have a convenient identifier and a descriptive label.

View File

@@ -31,7 +31,7 @@
"lint:fix": "eslint --cache --cache-strategy content --fix . && prettier --write . && tsx scripts/fixCSpell.ts",
"lint:jison": "tsx ./scripts/jison/lint.mts",
"contributors": "tsx scripts/updateContributors.ts",
"cypress": "cypress run",
"cypress": "cypress run --spec ./cypress/integration/rendering/appli.spec.js",
"cypress:open": "cypress open",
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
"e2e:coverage": "start-server-and-test dev:coverage http://localhost:9000/ cypress",

View File

@@ -78,187 +78,3 @@ describe('when working with site config', () => {
expect(config_4.altFontFamily).toBeUndefined();
});
});
describe('getUserDefinedConfig', () => {
beforeEach(() => {
configApi.reset();
});
it('should return empty object when no user config is defined', () => {
const userConfig = configApi.getUserDefinedConfig();
expect(userConfig).toEqual({});
});
it('should return config from initialize only', () => {
const initConfig: MermaidConfig = { theme: 'dark', fontFamily: 'Arial' };
configApi.saveConfigFromInitialize(initConfig);
const userConfig = configApi.getUserDefinedConfig();
expect(userConfig).toEqual(initConfig);
});
it('should return config from directives only', () => {
const directive1: MermaidConfig = { layout: 'elk', fontSize: 14 };
const directive2: MermaidConfig = { theme: 'forest' };
configApi.addDirective(directive1);
configApi.addDirective(directive2);
expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(`
{
"fontFamily": "Arial",
"fontSize": 14,
"layout": "elk",
"theme": "forest",
}
`);
});
it('should combine initialize config and directives', () => {
const initConfig: MermaidConfig = { theme: 'dark', fontFamily: 'Arial', layout: 'dagre' };
const directive1: MermaidConfig = { layout: 'elk', fontSize: 14 };
const directive2: MermaidConfig = { theme: 'forest' };
configApi.saveConfigFromInitialize(initConfig);
configApi.addDirective(directive1);
configApi.addDirective(directive2);
const userConfig = configApi.getUserDefinedConfig();
expect(userConfig).toMatchInlineSnapshot(`
{
"fontFamily": "Arial",
"fontSize": 14,
"layout": "elk",
"theme": "forest",
}
`);
});
it('should handle nested config objects properly', () => {
const initConfig: MermaidConfig = {
flowchart: { nodeSpacing: 50, rankSpacing: 100 },
theme: 'default',
};
const directive: MermaidConfig = {
flowchart: { nodeSpacing: 75, curve: 'basis' },
mindmap: { padding: 20 },
};
configApi.saveConfigFromInitialize(initConfig);
configApi.addDirective(directive);
const userConfig = configApi.getUserDefinedConfig();
expect(userConfig).toMatchInlineSnapshot(`
{
"flowchart": {
"curve": "basis",
"nodeSpacing": 75,
"rankSpacing": 100,
},
"mindmap": {
"padding": 20,
},
"theme": "default",
}
`);
});
it('should handle complex nested overrides', () => {
const initConfig: MermaidConfig = {
flowchart: {
nodeSpacing: 50,
rankSpacing: 100,
curve: 'linear',
},
theme: 'default',
};
const directive1: MermaidConfig = {
flowchart: {
nodeSpacing: 75,
},
fontSize: 12,
};
const directive2: MermaidConfig = {
flowchart: {
curve: 'basis',
nodeSpacing: 100,
},
mindmap: {
padding: 15,
},
};
configApi.saveConfigFromInitialize(initConfig);
configApi.addDirective(directive1);
configApi.addDirective(directive2);
const userConfig = configApi.getUserDefinedConfig();
expect(userConfig).toMatchInlineSnapshot(`
{
"flowchart": {
"curve": "basis",
"nodeSpacing": 100,
"rankSpacing": 100,
},
"fontSize": 12,
"mindmap": {
"padding": 15,
},
"theme": "default",
}
`);
});
it('should return independent copies (not references)', () => {
const initConfig: MermaidConfig = { theme: 'dark', flowchart: { nodeSpacing: 50 } };
configApi.saveConfigFromInitialize(initConfig);
const userConfig1 = configApi.getUserDefinedConfig();
const userConfig2 = configApi.getUserDefinedConfig();
userConfig1.theme = 'neutral';
userConfig1.flowchart!.nodeSpacing = 999;
expect(userConfig2).toMatchInlineSnapshot(`
{
"flowchart": {
"nodeSpacing": 50,
},
"theme": "dark",
}
`);
});
it('should handle edge cases with undefined values', () => {
const initConfig: MermaidConfig = { theme: 'dark', layout: undefined };
const directive: MermaidConfig = { fontSize: 14, fontFamily: undefined };
configApi.saveConfigFromInitialize(initConfig);
configApi.addDirective(directive);
expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(`
{
"fontSize": 14,
"layout": undefined,
"theme": "dark",
}
`);
});
it('should retain config from initialize after reset', () => {
const initConfig: MermaidConfig = { theme: 'dark' };
const directive: MermaidConfig = { layout: 'elk' };
configApi.saveConfigFromInitialize(initConfig);
configApi.addDirective(directive);
expect(configApi.getUserDefinedConfig()).toMatchInlineSnapshot(`
{
"layout": "elk",
"theme": "dark",
}
`);
configApi.reset();
});
});

View File

@@ -248,17 +248,3 @@ const checkConfig = (config: MermaidConfig) => {
issueWarning('LAZY_LOAD_DEPRECATED');
}
};
export const getUserDefinedConfig = (): MermaidConfig => {
let userConfig: MermaidConfig = {};
if (configFromInitialize) {
userConfig = assignWithDepth(userConfig, configFromInitialize);
}
for (const d of directives) {
userConfig = assignWithDepth(userConfig, d);
}
return userConfig;
};

View File

@@ -14,7 +14,7 @@
// Special states for recognizing aliases
// A special state for grabbing text up to the first comment/newline
%x ID ALIAS LINE CONFIG CONFIG_DATA
%x ID ALIAS LINE
%x acc_title
%x acc_descr
@@ -28,11 +28,6 @@
\%%(?!\{)[^\n]* /* skip comments */
[^\}]\%\%[^\n]* /* skip comments */
[0-9]+(?=[ \n]+) return 'NUM';
<ID>\@\{ { this.begin('CONFIG'); return 'CONFIG_START'; }
<CONFIG>[^\}]+ { return 'CONFIG_CONTENT'; }
<CONFIG>\} { this.popState(); this.popState(); return 'CONFIG_END'; }
<ID>[^\<->\->:\n,;@\s]+(?=\@\{) { yytext = yytext.trim(); return 'ACTOR'; }
<ID>[^\<->\->:\n,;@]+?([\-]*[^\<->\->:\n,;@]+?)*?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
"box" { this.begin('LINE'); return 'box'; }
"participant" { this.begin('ID'); return 'participant'; }
"actor" { this.begin('ID'); return 'participant_actor'; }
@@ -236,8 +231,6 @@ participant_statement
| 'participant_actor' actor 'AS' restOfLine 'NEWLINE' {$2.draw='actor'; $2.type='addParticipant';$2.description=yy.parseMessage($4); $$=$2;}
| 'participant_actor' actor 'NEWLINE' {$2.draw='actor'; $2.type='addParticipant'; $$=$2;}
| 'destroy' actor 'NEWLINE' {$2.type='destroyParticipant'; $$=$2;}
| 'participant' actor_with_config 'NEWLINE' {$2.draw='participant'; $2.type='addParticipant'; $$=$2;}
;
note_statement
@@ -308,23 +301,6 @@ signal
{ $$ = [$1,$3,{type: 'addMessage', from:$1.actor, to:$3.actor, signalType:$2, msg:$4}]}
;
actor_with_config
: ACTOR config_object
{
$$ = {
type: 'addParticipant',
actor: $1,
config: $2
};
}
;
config_object
: CONFIG_START CONFIG_CONTENT CONFIG_END
{
$$ = $2.trim();
}
;
// actor
// : actor_participant
// | actor_actor
@@ -337,7 +313,7 @@ signaltype
: SOLID_OPEN_ARROW { $$ = yy.LINETYPE.SOLID_OPEN; }
| DOTTED_OPEN_ARROW { $$ = yy.LINETYPE.DOTTED_OPEN; }
| SOLID_ARROW { $$ = yy.LINETYPE.SOLID; }
| BIDIRECTIONAL_SOLID_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_SOLID; }
| BIDIRECTIONAL_SOLID_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_SOLID; }
| DOTTED_ARROW { $$ = yy.LINETYPE.DOTTED; }
| BIDIRECTIONAL_DOTTED_ARROW { $$ = yy.LINETYPE.BIDIRECTIONAL_DOTTED; }
| SOLID_CROSS { $$ = yy.LINETYPE.SOLID_CROSS; }

View File

@@ -1,5 +1,4 @@
import { getConfig } from '../../diagram-api/diagramAPI.js';
import * as yaml from 'js-yaml';
import type { DiagramDB } from '../../diagram-api/types.js';
import { log } from '../../logger.js';
import { ImperativeState } from '../../utils/imperativeState.js';
@@ -14,7 +13,6 @@ import {
setDiagramTitle,
} from '../common/commonDb.js';
import type { Actor, AddMessageParams, Box, Message, Note } from './types.js';
import type { ParticipantMetaData } from '../../types.js';
interface SequenceState {
prevActor?: string;
@@ -77,17 +75,6 @@ const PLACEMENT = {
OVER: 2,
} as const;
export const PARTICIPANT_TYPE = {
ACTOR: 'actor',
BOUNDARY: 'boundary',
COLLECTIONS: 'collections',
CONTROL: 'control',
DATABASE: 'database',
ENTITY: 'entity',
PARTICIPANT: 'participant',
QUEUE: 'queue',
} as const;
export class SequenceDB implements DiagramDB {
private readonly state = new ImperativeState<SequenceState>(() => ({
prevActor: undefined,
@@ -132,22 +119,9 @@ export class SequenceDB implements DiagramDB {
id: string,
name: string,
description: { text: string; wrap?: boolean | null; type: string },
type: string,
metadata?: any
type: string
) {
let assignedBox = this.state.records.currentBox;
let doc;
if (metadata !== undefined) {
let yamlData;
// detect if shapeData contains a newline character
if (!metadata.includes('\n')) {
yamlData = '{\n' + metadata + '\n}';
} else {
yamlData = metadata + '\n';
}
doc = yaml.load(yamlData, { schema: yaml.JSON_SCHEMA }) as ParticipantMetaData;
}
type = doc?.type ?? type;
const old = this.state.records.actors.get(id);
if (old) {
// If already set and trying to set to a new one throw error
@@ -544,7 +518,7 @@ export class SequenceDB implements DiagramDB {
});
break;
case 'addParticipant':
this.addActor(param.actor, param.actor, param.description, param.draw, param.config);
this.addActor(param.actor, param.actor, param.description, param.draw);
break;
case 'createParticipant':
if (this.state.records.actors.has(param.actor)) {
@@ -553,7 +527,7 @@ export class SequenceDB implements DiagramDB {
);
}
this.state.records.lastCreated = param.actor;
this.addActor(param.actor, param.actor, param.description, param.draw, param.config);
this.addActor(param.actor, param.actor, param.description, param.draw);
this.state.records.createdActors.set(param.actor, this.state.records.messages.length);
break;
case 'destroyParticipant':

View File

@@ -2058,272 +2058,4 @@ Bob->>Alice:Got it!
expect(messages[0].from).toBe('Alice');
expect(messages[0].to).toBe('Bob');
});
describe('when parsing extended participant syntax', () => {
it('should parse participants with different quote styles and whitespace', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice@{ "type" : "database" }
participant Bob@{ "type" : "database" }
participant Carl@{ type: "database" }
participant David@{ "type" : 'database' }
participant Eve@{ type: 'database' }
participant Favela@{ "type" : "database" }
Bob->>+Alice: Hi Alice
Alice->>+Bob: Hi Bob
`);
const actors = diagram.db.getActors();
expect(actors.get('Alice').type).toBe('database');
expect(actors.get('Alice').description).toBe('Alice');
expect(actors.get('Bob').type).toBe('database');
expect(actors.get('Bob').description).toBe('Bob');
expect(actors.get('Carl').type).toBe('database');
expect(actors.get('Carl').description).toBe('Carl');
expect(actors.get('David').type).toBe('database');
expect(actors.get('David').description).toBe('David');
expect(actors.get('Eve').type).toBe('database');
expect(actors.get('Eve').description).toBe('Eve');
expect(actors.get('Favela').type).toBe('database');
expect(actors.get('Favela').description).toBe('Favela');
// Verify messages were parsed correctly
const messages = diagram.db.getMessages();
expect(messages.length).toBe(4); // 2 messages + 2 activation messages
expect(messages[0].from).toBe('Bob');
expect(messages[0].to).toBe('Alice');
expect(messages[0].message).toBe('Hi Alice');
expect(messages[2].from).toBe('Alice'); // Second message (index 2 due to activation)
expect(messages[2].to).toBe('Bob');
expect(messages[2].message).toBe('Hi Bob');
});
it('should parse mixed participant types with extended syntax', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant lead
participant dsa@{ "type" : "queue" }
API->>+Database: getUserb
Database-->>-API: userb
dsa --> Database: hello
`);
// Verify actors were created
const actors = diagram.db.getActors();
expect(actors.get('lead').type).toBe('participant');
expect(actors.get('lead').description).toBe('lead');
// Participant with extended syntax
expect(actors.get('dsa').type).toBe('queue');
expect(actors.get('dsa').description).toBe('dsa');
// Implicitly created actors (from messages)
expect(actors.get('API').type).toBe('participant');
expect(actors.get('API').description).toBe('API');
expect(actors.get('Database').type).toBe('participant');
expect(actors.get('Database').description).toBe('Database');
// Verify messages were parsed correctly
const messages = diagram.db.getMessages();
expect(messages.length).toBe(5); // 3 messages + 2 activation messages
// First message with activation
expect(messages[0].from).toBe('API');
expect(messages[0].to).toBe('Database');
expect(messages[0].message).toBe('getUserb');
expect(messages[0].activate).toBe(true);
// Second message with deactivation
expect(messages[2].from).toBe('Database');
expect(messages[2].to).toBe('API');
expect(messages[2].message).toBe('userb');
// Third message
expect(messages[4].from).toBe('dsa');
expect(messages[4].to).toBe('Database');
expect(messages[4].message).toBe('hello');
});
it('should fail for malformed JSON in participant definition', async () => {
const invalidDiagram = `
sequenceDiagram
participant D@{ "type: "entity" }
participant E@{ "type": "dat
abase }
`;
let error = false;
try {
await mermaidAPI.parse(invalidDiagram);
} catch (e) {
error = true;
}
expect(error).toBe(true);
});
it('should fail for missing colon separator', async () => {
const invalidDiagram = `
sequenceDiagram
participant C@{ "type" "control" }
C ->> C: action
`;
let error = false;
try {
await mermaidAPI.parse(invalidDiagram);
} catch (e) {
error = true;
}
expect(error).toBe(true);
});
it('should fail for missing closing brace', async () => {
const invalidDiagram = `
sequenceDiagram
participant E@{ "type": "entity"
E ->> E: process
`;
let error = false;
try {
await mermaidAPI.parse(invalidDiagram);
} catch (e) {
error = true;
}
expect(error).toBe(true);
});
});
describe('participant type parsing', () => {
it('should parse boundary participant', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant boundary@{ "type" : "boundary" }
boundary->boundary: test
`);
const actors = diagram.db.getActors();
expect(actors.get('boundary').type).toBe('boundary');
expect(actors.get('boundary').description).toBe('boundary');
});
it('should parse control participant', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant C@{ "type" : "control" }
C->C: test
`);
const actors = diagram.db.getActors();
expect(actors.get('C').type).toBe('control');
expect(actors.get('C').description).toBe('C');
});
it('should parse entity participant', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant E@{ "type" : "entity" }
E->E: test
`);
const actors = diagram.db.getActors();
expect(actors.get('E').type).toBe('entity');
expect(actors.get('E').description).toBe('E');
});
it('should parse database participant', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant D@{ "type" : "database" }
D->D: test
`);
const actors = diagram.db.getActors();
expect(actors.get('D').type).toBe('database');
expect(actors.get('D').description).toBe('D');
});
it('should parse collections participant', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant L@{ "type" : "collections" }
L->L: test
`);
const actors = diagram.db.getActors();
expect(actors.get('L').type).toBe('collections');
expect(actors.get('L').description).toBe('L');
});
it('should parse queue participant', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Q@{ "type" : "queue" }
Q->Q: test
`);
const actors = diagram.db.getActors();
expect(actors.get('Q').type).toBe('queue');
expect(actors.get('Q').description).toBe('Q');
});
});
describe('participant type parsing', () => {
it('should parse actor participant', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant A@{ "type" : "queue" }
A->A: test
`);
const actors = diagram.db.getActors();
expect(actors.get('A').type).toBe('queue');
expect(actors.get('A').description).toBe('A');
});
it('should parse participant participant', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant P@{ "type" : "database" }
P->P: test
`);
const actors = diagram.db.getActors();
expect(actors.get('P').type).toBe('database');
expect(actors.get('P').description).toBe('P');
});
it('should parse boundary using actor keyword', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant Alice@{ "type" : "collections" }
participant Bob@{ "type" : "control" }
Alice->>Bob: Hello Bob, how are you?
`);
const actors = diagram.db.getActors();
expect(actors.get('Alice').type).toBe('collections');
expect(actors.get('Bob').type).toBe('control');
expect(actors.get('Bob').description).toBe('Bob');
});
it('should parse control using participant keyword', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant C@{ "type" : "control" }
C->C: test
`);
const actors = diagram.db.getActors();
expect(actors.get('C').type).toBe('control');
expect(actors.get('C').description).toBe('C');
});
it('should parse entity using actor keyword', async () => {
const diagram = await Diagram.fromText(`
sequenceDiagram
participant E@{ "type" : "entity" }
E->E: test
`);
const actors = diagram.db.getActors();
expect(actors.get('E').type).toBe('entity');
expect(actors.get('E').description).toBe('E');
});
});
});

View File

@@ -10,7 +10,6 @@ import assignWithDepth from '../../assignWithDepth.js';
import utils from '../../utils.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import type { Diagram } from '../../Diagram.js';
import { PARTICIPANT_TYPE } from './sequenceDb.js';
let conf = {};
@@ -477,29 +476,7 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO
// add node number
if (sequenceVisible || conf.showSequenceNumbers) {
const isBidirectional =
type === diagObj.db.LINETYPE.BIDIRECTIONAL_SOLID ||
type === diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED;
if (isBidirectional) {
const SEQUENCE_NUMBER_RADIUS = 6;
if (startx < stopx) {
line.attr('x1', startx + 2 * SEQUENCE_NUMBER_RADIUS);
} else {
line.attr('x1', startx + SEQUENCE_NUMBER_RADIUS);
}
}
diagram
.append('line')
.attr('x1', startx)
.attr('y1', lineStartY)
.attr('x2', startx)
.attr('y2', lineStartY)
.attr('stroke-width', 0)
.attr('marker-start', 'url(' + url + '#sequencenumber)');
line.attr('marker-start', 'url(' + url + '#sequencenumber)');
diagram
.append('text')
.attr('x', startx)
@@ -747,19 +724,11 @@ function adjustCreatedDestroyedData(
msgModel.startx = msgModel.startx - adjustment;
}
}
const actorArray = [
PARTICIPANT_TYPE.ACTOR,
PARTICIPANT_TYPE.CONTROL,
PARTICIPANT_TYPE.ENTITY,
PARTICIPANT_TYPE.DATABASE,
];
// if it is a create message
if (createdActors.get(msg.to) == index) {
const actor = actors.get(msg.to);
const adjustment = actorArray.includes(actor.type)
? ACTOR_TYPE_WIDTH / 2 + 3
: actor.width / 2 + 3;
const adjustment = actor.type == 'actor' ? ACTOR_TYPE_WIDTH / 2 + 3 : actor.width / 2 + 3;
receiverAdjustment(actor, adjustment);
actor.starty = lineStartY - actor.height / 2;
bounds.bumpVerticalPos(actor.height / 2);
@@ -768,7 +737,7 @@ function adjustCreatedDestroyedData(
else if (destroyedActors.get(msg.from) == index) {
const actor = actors.get(msg.from);
if (conf.mirrorActors) {
const adjustment = actorArray.includes(actor.type) ? ACTOR_TYPE_WIDTH / 2 : actor.width / 2;
const adjustment = actor.type == 'actor' ? ACTOR_TYPE_WIDTH / 2 : actor.width / 2;
senderAdjustment(actor, adjustment);
}
actor.stopy = lineStartY - actor.height / 2;
@@ -778,9 +747,7 @@ function adjustCreatedDestroyedData(
else if (destroyedActors.get(msg.to) == index) {
const actor = actors.get(msg.to);
if (conf.mirrorActors) {
const adjustment = actorArray.includes(actor.type)
? ACTOR_TYPE_WIDTH / 2 + 3
: actor.width / 2 + 3;
const adjustment = actor.type == 'actor' ? ACTOR_TYPE_WIDTH / 2 + 3 : actor.width / 2 + 3;
receiverAdjustment(actor, adjustment);
}
actor.stopy = lineStartY - actor.height / 2;
@@ -1098,11 +1065,10 @@ export const draw = async function (_text: string, id: string, _version: string,
for (const box of bounds.models.boxes) {
box.height = bounds.getVerticalPos() - box.y;
bounds.insert(box.x, box.y, box.x + box.width, box.height);
const boxPadding = conf.boxMargin * 2;
box.startx = box.x - boxPadding;
box.starty = box.y - boxPadding * 0.25;
box.stopx = box.startx + box.width + 2 * boxPadding;
box.stopy = box.starty + box.height + boxPadding * 0.75;
box.startx = box.x;
box.starty = box.y;
box.stopx = box.startx + box.width;
box.stopy = box.starty + box.height;
box.stroke = 'rgb(0,0,0, 0.5)';
svgDraw.drawBox(diagram, box, conf);
}
@@ -1367,9 +1333,6 @@ async function calculateActorMargins(
return (total += actors.get(aKey).width + (actors.get(aKey).margin || 0));
}, 0);
const standardBoxPadding = conf.boxMargin * 8;
totalWidth += standardBoxPadding;
totalWidth -= 2 * conf.boxTextMargin;
if (box.wrap) {
box.name = utils.wrapLabel(box.name, totalWidth - 2 * conf.wrapPadding, textFont);

View File

@@ -12,11 +12,6 @@ const getStyles = (options) =>
.actor-line {
stroke: ${options.actorLineColor};
}
.innerArc {
stroke-width: 1.5;
stroke-dasharray: none;
}
.messageLine0 {
stroke-width: 1.5;
@@ -120,7 +115,6 @@ const getStyles = (options) =>
fill: ${options.actorBkg};
stroke-width: 2px;
}
`;
export default getStyles;

View File

@@ -415,600 +415,6 @@ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) {
return height;
};
/**
* Draws an actor in the diagram with the attached line
*
* @param {any} elem - The diagram we'll draw to.
* @param {any} actor - The actor to draw.
* @param {any} conf - DrawText implementation discriminator object
* @param {boolean} isFooter - If the actor is the footer one
*/
const drawActorTypeCollections = function (elem, actor, conf, isFooter) {
const actorY = isFooter ? actor.stopy : actor.starty;
const center = actor.x + actor.width / 2;
const centerY = actorY + actor.height;
const boxplusLineGroup = elem.append('g').lower();
var g = boxplusLineGroup;
if (!isFooter) {
actorCnt++;
if (Object.keys(actor.links || {}).length && !conf.forceMenus) {
g.attr('onclick', popupMenuToggle(`actor${actorCnt}_popup`)).attr('cursor', 'pointer');
}
g.append('line')
.attr('id', 'actor' + actorCnt)
.attr('x1', center)
.attr('y1', centerY)
.attr('x2', center)
.attr('y2', 2000)
.attr('class', 'actor-line 200')
.attr('stroke-width', '0.5px')
.attr('stroke', '#999')
.attr('name', actor.name);
g = boxplusLineGroup.append('g');
actor.actorCnt = actorCnt;
if (actor.links != null) {
g.attr('id', 'root-' + actorCnt);
}
}
const rect = svgDrawCommon.getNoteRect();
var cssclass = 'actor';
if (actor.properties?.class) {
cssclass = actor.properties.class;
} else {
rect.fill = '#eaeaea';
}
if (isFooter) {
cssclass += ` ${BOTTOM_ACTOR_CLASS}`;
} else {
cssclass += ` ${TOP_ACTOR_CLASS}`;
}
rect.x = actor.x;
rect.y = actorY;
rect.width = actor.width;
rect.height = actor.height;
rect.class = cssclass;
rect.name = actor.name;
// DRAW STACKED RECTANGLES
const offset = 6;
const shadowRect = {
...rect,
x: rect.x + (isFooter ? -offset : -offset),
y: rect.y + (isFooter ? +offset : +offset),
class: 'actor',
};
const rectElem = drawRect(g, rect); // draw main rectangle on top
drawRect(g, shadowRect);
actor.rectData = rect;
if (actor.properties?.icon) {
const iconSrc = actor.properties.icon.trim();
if (iconSrc.charAt(0) === '@') {
svgDrawCommon.drawEmbeddedImage(g, rect.x + rect.width - 20, rect.y + 10, iconSrc.substr(1));
} else {
svgDrawCommon.drawImage(g, rect.x + rect.width - 20, rect.y + 10, iconSrc);
}
}
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
actor.description,
g,
rect.x - offset,
rect.y + offset,
rect.width,
rect.height,
{ class: `actor ${ACTOR_BOX_CLASS}` },
conf
);
let height = actor.height;
if (rectElem.node) {
const bounds = rectElem.node().getBBox();
actor.height = bounds.height;
height = bounds.height;
}
return height;
};
const drawActorTypeQueue = function (elem, actor, conf, isFooter) {
const actorY = isFooter ? actor.stopy : actor.starty;
const center = actor.x + actor.width / 2;
const centerY = actorY + actor.height;
const boxplusLineGroup = elem.append('g').lower();
let g = boxplusLineGroup;
if (!isFooter) {
actorCnt++;
if (Object.keys(actor.links || {}).length && !conf.forceMenus) {
g.attr('onclick', popupMenuToggle(`actor${actorCnt}_popup`)).attr('cursor', 'pointer');
}
g.append('line')
.attr('id', 'actor' + actorCnt)
.attr('x1', center)
.attr('y1', centerY)
.attr('x2', center)
.attr('y2', 2000)
.attr('class', 'actor-line 200')
.attr('stroke-width', '0.5px')
.attr('stroke', '#999')
.attr('name', actor.name);
g = boxplusLineGroup.append('g');
actor.actorCnt = actorCnt;
if (actor.links != null) {
g.attr('id', 'root-' + actorCnt);
}
}
const rect = svgDrawCommon.getNoteRect();
let cssclass = 'actor';
if (actor.properties?.class) {
cssclass = actor.properties.class;
} else {
rect.fill = '#eaeaea';
}
if (isFooter) {
cssclass += ` ${BOTTOM_ACTOR_CLASS}`;
} else {
cssclass += ` ${TOP_ACTOR_CLASS}`;
}
rect.x = actor.x;
rect.y = actorY;
rect.width = actor.width;
rect.height = actor.height;
rect.class = cssclass;
rect.name = actor.name;
// Cylinder dimensions
const ry = rect.height / 2;
const rx = ry / (2.5 + rect.height / 50);
// Cylinder base group
const cylinderGroup = g.append('g');
const cylinderArc = g.append('g');
// Main cylinder body
cylinderGroup
.append('path')
.attr(
'd',
`M ${rect.x},${rect.y + ry}
a ${rx},${ry} 0 0 0 0,${rect.height}
h ${rect.width - 2 * rx}
a ${rx},${ry} 0 0 0 0,-${rect.height}
Z
`
)
.attr('class', cssclass);
cylinderArc
.append('path')
.attr(
'd',
`M ${rect.x},${rect.y + ry}
a ${rx},${ry} 0 0 0 0,${rect.height}`
)
.attr('stroke', '#666')
.attr('stroke-width', '1px')
.attr('class', cssclass);
cylinderGroup.attr('transform', `translate(${rx}, ${-(rect.height / 2)})`);
cylinderArc.attr('transform', `translate(${rect.width - rx}, ${-rect.height / 2})`);
actor.rectData = rect;
if (actor.properties?.icon) {
const iconSrc = actor.properties.icon.trim();
const iconX = rect.x + rect.width - 20;
const iconY = rect.y + 10;
if (iconSrc.charAt(0) === '@') {
svgDrawCommon.drawEmbeddedImage(g, iconX, iconY, iconSrc.substr(1));
} else {
svgDrawCommon.drawImage(g, iconX, iconY, iconSrc);
}
}
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
actor.description,
g,
rect.x,
rect.y,
rect.width,
rect.height,
{ class: `actor ${ACTOR_BOX_CLASS}` },
conf
);
let height = actor.height;
const lastPath = cylinderGroup.select('path:last-child');
if (lastPath.node()) {
const bounds = lastPath.node().getBBox();
actor.height = bounds.height;
height = bounds.height;
}
return height;
};
const drawActorTypeControl = function (elem, actor, conf, isFooter) {
const actorY = isFooter ? actor.stopy : actor.starty;
const center = actor.x + actor.width / 2;
const centerY = actorY + 75;
const line = elem.append('g').lower();
if (!isFooter) {
actorCnt++;
line
.append('line')
.attr('id', 'actor' + actorCnt)
.attr('x1', center)
.attr('y1', centerY)
.attr('x2', center)
.attr('y2', 2000)
.attr('class', 'actor-line 200')
.attr('stroke-width', '0.5px')
.attr('stroke', '#999')
.attr('name', actor.name);
actor.actorCnt = actorCnt;
}
const actElem = elem.append('g');
let cssClass = ACTOR_MAN_FIGURE_CLASS;
if (isFooter) {
cssClass += ` ${BOTTOM_ACTOR_CLASS}`;
} else {
cssClass += ` ${TOP_ACTOR_CLASS}`;
}
actElem.attr('class', cssClass);
actElem.attr('name', actor.name);
const rect = svgDrawCommon.getNoteRect();
rect.x = actor.x;
rect.y = actorY;
rect.fill = '#eaeaea';
rect.width = actor.width;
rect.height = actor.height;
rect.class = 'actor';
const cx = actor.x + actor.width / 2;
const cy = actorY + 30;
const r = 18;
actElem
.append('defs')
.append('marker')
.attr('id', 'filled-head-control')
.attr('refX', 11)
.attr('refY', 5.8)
.attr('markerWidth', 20)
.attr('markerHeight', 28)
.attr('orient', '172.5')
.append('path')
.attr('d', 'M 14.4 5.6 L 7.2 10.4 L 8.8 5.6 L 7.2 0.8 Z');
// Draw the base circle
actElem
.append('circle')
.attr('cx', cx)
.attr('cy', cy)
.attr('r', r)
.attr('fill', '#eaeaf7')
.attr('stroke', '#666')
.attr('stroke-width', 1.2);
// Draw looping arrow as arc path
actElem
.append('line')
.attr('marker-end', 'url(#filled-head-control)')
.attr('transform', `translate(${cx}, ${cy - r})`);
const bounds = actElem.node().getBBox();
actor.height = bounds.height + 2 * (conf?.sequence?.labelBoxHeight ?? 0);
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
actor.description,
actElem,
rect.x,
rect.y + r + (isFooter ? 5 : 10),
rect.width,
rect.height,
{ class: `actor ${ACTOR_MAN_FIGURE_CLASS}` },
conf
);
return actor.height;
};
const drawActorTypeEntity = function (elem, actor, conf, isFooter) {
const actorY = isFooter ? actor.stopy : actor.starty;
const center = actor.x + actor.width / 2;
const centerY = actorY + 75;
const line = elem.append('g').lower();
const actElem = elem.append('g');
let cssClass = ACTOR_MAN_FIGURE_CLASS;
if (isFooter) {
cssClass += ` ${BOTTOM_ACTOR_CLASS}`;
} else {
cssClass += ` ${TOP_ACTOR_CLASS}`;
}
actElem.attr('class', cssClass);
actElem.attr('name', actor.name);
const rect = svgDrawCommon.getNoteRect();
rect.x = actor.x;
rect.y = actorY;
rect.fill = '#eaeaea';
rect.width = actor.width;
rect.height = actor.height;
rect.class = 'actor';
const cx = actor.x + actor.width / 2;
const cy = actorY + (!isFooter ? 25 : 10);
const r = 18;
actElem
.append('circle')
.attr('cx', cx)
.attr('cy', cy)
.attr('r', r)
.attr('width', actor.width)
.attr('height', actor.height);
actElem
.append('line')
.attr('x1', cx - r)
.attr('x2', cx + r)
.attr('y1', cy + r)
.attr('y2', cy + r)
.attr('stroke', '#333')
.attr('stroke-width', 2);
const bounds = actElem.node().getBBox();
actor.height = bounds.height + (conf?.sequence?.labelBoxHeight ?? 0);
if (!isFooter) {
actorCnt++;
line
.append('line')
.attr('id', 'actor' + actorCnt)
.attr('x1', center)
.attr('y1', centerY)
.attr('x2', center)
.attr('y2', 2000)
.attr('class', 'actor-line 200')
.attr('stroke-width', '0.5px')
.attr('stroke', '#999')
.attr('name', actor.name);
actor.actorCnt = actorCnt;
}
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
actor.description,
actElem,
rect.x,
rect.y + (!isFooter ? (cy + r - actorY) / 2 : (cy - actorY + r - 5) / 2),
rect.width,
rect.height,
{ class: `actor ${ACTOR_MAN_FIGURE_CLASS}` },
conf
);
if (!isFooter) {
actElem.attr('transform', `translate(${0}, ${r / 2})`);
} else {
actElem.attr('transform', `translate(${0}, ${r / 2})`);
}
return actor.height;
};
const drawActorTypeDatabase = function (elem, actor, conf, isFooter) {
const actorY = isFooter ? actor.stopy : actor.starty;
const center = actor.x + actor.width / 2;
const centerY = actorY + actor.height + 2 * conf.boxTextMargin;
const boxplusLineGroup = elem.append('g').lower();
let g = boxplusLineGroup;
if (!isFooter) {
actorCnt++;
if (Object.keys(actor.links || {}).length && !conf.forceMenus) {
g.attr('onclick', popupMenuToggle(`actor${actorCnt}_popup`)).attr('cursor', 'pointer');
}
g.append('line')
.attr('id', 'actor' + actorCnt)
.attr('x1', center)
.attr('y1', centerY)
.attr('x2', center)
.attr('y2', 2000)
.attr('class', 'actor-line 200')
.attr('stroke-width', '0.5px')
.attr('stroke', '#999')
.attr('name', actor.name);
g = boxplusLineGroup.append('g');
actor.actorCnt = actorCnt;
if (actor.links != null) {
g.attr('id', 'root-' + actorCnt);
}
}
const rect = svgDrawCommon.getNoteRect();
let cssclass = 'actor';
if (actor.properties?.class) {
cssclass = actor.properties.class;
} else {
rect.fill = '#eaeaea';
}
if (isFooter) {
cssclass += ` ${BOTTOM_ACTOR_CLASS}`;
} else {
cssclass += ` ${TOP_ACTOR_CLASS}`;
}
rect.x = actor.x;
rect.y = actorY;
rect.width = actor.width;
rect.height = actor.height;
rect.class = cssclass;
rect.name = actor.name;
// Cylinder dimensions
rect.x = actor.x;
rect.y = actorY;
const w = rect.width / 4;
const h = rect.width / 4;
const rx = w / 2;
const ry = rx / (2.5 + w / 50);
// Cylinder base group
const cylinderGroup = g.append('g');
const d = `
M ${rect.x},${rect.y + ry}
a ${rx},${ry} 0 0 0 ${w},0
a ${rx},${ry} 0 0 0 -${w},0
l 0,${h - 2 * ry}
a ${rx},${ry} 0 0 0 ${w},0
l 0,-${h - 2 * ry}
`;
// Draw the main cylinder body
cylinderGroup
.append('path')
.attr('d', d)
.attr('fill', '#eaeaea')
.attr('stroke', '#000')
.attr('stroke-width', 1)
.attr('class', cssclass);
if (!isFooter) {
cylinderGroup.attr('transform', `translate(${w * 1.5}, ${(rect.height + ry) / 4})`);
} else {
cylinderGroup.attr('transform', `translate(${w * 1.5}, ${rect.height / 4 - 2 * ry})`);
}
actor.rectData = rect;
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
actor.description,
g,
rect.x,
rect.y + (!isFooter ? (rect.height + ry) / 2 : (rect.height + h) / 4),
rect.width,
rect.height,
{ class: `actor ${ACTOR_BOX_CLASS}` },
conf
);
const lastPath = cylinderGroup.select('path:last-child');
if (lastPath.node()) {
const bounds = lastPath.node().getBBox();
actor.height = bounds.height + (conf.sequence.labelBoxHeight ?? 0);
}
return actor.height;
};
const drawActorTypeBoundary = function (elem, actor, conf, isFooter) {
const actorY = isFooter ? actor.stopy : actor.starty;
const center = actor.x + actor.width / 2;
const centerY = actorY + 80;
const radius = 30;
const line = elem.append('g').lower();
if (!isFooter) {
actorCnt++;
line
.append('line')
.attr('id', 'actor' + actorCnt)
.attr('x1', center)
.attr('y1', centerY)
.attr('x2', center)
.attr('y2', 2000)
.attr('class', 'actor-line 200')
.attr('stroke-width', '0.5px')
.attr('stroke', '#999')
.attr('name', actor.name);
actor.actorCnt = actorCnt;
}
const actElem = elem.append('g');
let cssClass = ACTOR_MAN_FIGURE_CLASS;
if (isFooter) {
cssClass += ` ${BOTTOM_ACTOR_CLASS}`;
} else {
cssClass += ` ${TOP_ACTOR_CLASS}`;
}
actElem.attr('class', cssClass);
actElem.attr('name', actor.name);
const rect = svgDrawCommon.getNoteRect();
rect.x = actor.x;
rect.y = actorY;
rect.fill = '#eaeaea';
rect.width = actor.width;
rect.height = actor.height;
rect.class = 'actor';
actElem
.append('line')
.attr('id', 'actor-man-torso' + actorCnt)
.attr('x1', actor.x + actor.width / 2 - radius * 2.5)
.attr('y1', actorY + 10)
.attr('x2', actor.x + actor.width / 2 - 15)
.attr('y2', actorY + 10);
actElem
.append('line')
.attr('id', 'actor-man-arms' + actorCnt)
.attr('x1', actor.x + actor.width / 2 - radius * 2.5)
.attr('y1', actorY + 0) // starting Y
.attr('x2', actor.x + actor.width / 2 - radius * 2.5)
.attr('y2', actorY + 20); // ending Y (26px long, adjust as needed)
actElem
.append('circle')
.attr('cx', actor.x + actor.width / 2)
.attr('cy', actorY + 10)
.attr('r', radius);
const bounds = actElem.node().getBBox();
actor.height = bounds.height + (conf.sequence.labelBoxHeight ?? 0);
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
actor.description,
actElem,
rect.x,
rect.y + (!isFooter ? radius / 2 + 3 : radius / 2 - 4),
rect.width,
rect.height,
{ class: `actor ${ACTOR_MAN_FIGURE_CLASS}` },
conf
);
if (!isFooter) {
actElem.attr('transform', `translate(0,${radius / 2 + 7})`);
} else {
actElem.attr('transform', `translate(0,${radius / 2 + 7})`);
}
return actor.height;
};
const drawActorTypeActor = function (elem, actor, conf, isFooter) {
const actorY = isFooter ? actor.stopy : actor.starty;
const center = actor.x + actor.width / 2;
@@ -1110,18 +516,6 @@ export const drawActor = async function (elem, actor, conf, isFooter) {
return await drawActorTypeActor(elem, actor, conf, isFooter);
case 'participant':
return await drawActorTypeParticipant(elem, actor, conf, isFooter);
case 'boundary':
return await drawActorTypeBoundary(elem, actor, conf, isFooter);
case 'control':
return await drawActorTypeControl(elem, actor, conf, isFooter);
case 'entity':
return await drawActorTypeEntity(elem, actor, conf, isFooter);
case 'database':
return await drawActorTypeDatabase(elem, actor, conf, isFooter);
case 'collections':
return await drawActorTypeCollections(elem, actor, conf, isFooter);
case 'queue':
return await drawActorTypeQueue(elem, actor, conf, isFooter);
}
};

View File

@@ -590,17 +590,11 @@ flowchart TD
- `b`
- **w**: The width of the image. If not defined, this will default to the natural width of the image.
- **h**: The height of the image. If not defined, this will default to the natural height of the image.
- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the width (`w`) accordingly to the height (`h`). If not defined, this will default to `off` Possible values are:
- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the height (`h`) accordingly to the width (`w`). If not defined, this will default to `off` Possible values are:
- `on`
- `off`
If you want to resize an image, but keep the same aspect ratio, set `h`, and set `constraint: on` to constrain the aspect ratio. E.g.
```mermaid
flowchart TD
%% My image with a constrained aspect ratio
A@{ img: "https://mermaid.js.org/favicon.svg", label: "My example image label", pos: "t", h: 60, constraint: "on" }
```
These new shapes provide additional flexibility and visual appeal to your flowcharts, making them more informative and engaging.
## Links between nodes

View File

@@ -46,78 +46,6 @@ sequenceDiagram
Bob->>Alice: Hi Alice
```
### Boundary
If you want to use the boundary symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "boundary" }
participant Bob
Alice->>Bob: Request from boundary
Bob->>Alice: Response to boundary
```
### Control
If you want to use the control symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "control" }
participant Bob
Alice->>Bob: Control request
Bob->>Alice: Control response
```
### Entity
If you want to use the entity symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "entity" }
participant Bob
Alice->>Bob: Entity request
Bob->>Alice: Entity response
```
### Database
If you want to use the database symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "database" }
participant Bob
Alice->>Bob: DB query
Bob->>Alice: DB result
```
### Collections
If you want to use the collections symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "collections" }
participant Bob
Alice->>Bob: Collections request
Bob->>Alice: Collections response
```
### Queue
If you want to use the queue symbol for a participant, use the JSON configuration syntax as shown below.
```mermaid-example
sequenceDiagram
participant Alice@{ "type" : "queue" }
participant Bob
Alice->>Bob: Queue message
Bob->>Alice: Queue response
```
### Aliases
The actor can have a convenient identifier and a descriptive label.

View File

@@ -13,18 +13,6 @@ export interface NodeMetaData {
ticket?: string;
}
export interface ParticipantMetaData {
type?:
| 'actor'
| 'participant'
| 'boundary'
| 'control'
| 'entity'
| 'database'
| 'collections'
| 'queue';
}
export interface EdgeMetaData {
animation?: 'fast' | 'slow';
animate?: boolean;

293
pnpm-lock.yaml generated
View File

@@ -15,7 +15,7 @@ importers:
devDependencies:
'@applitools/eyes-cypress':
specifier: ^3.44.9
version: 3.50.2(encoding@0.1.13)(typescript@5.7.3)
version: 3.53.2(encoding@0.1.13)(typescript@5.7.3)
'@argos-ci/cypress':
specifier: ^5.0.2
version: 5.0.2(cypress@14.5.1)
@@ -663,12 +663,12 @@ packages:
resolution: {integrity: sha512-OvyhwtYaWSTfo8NfibmFlgl+pIMaBOmN0OwZ3CPaGscEK3B8FCVDuQ7zgxY8seU/1kfSvNWnyB0DtKJyNLxX7g==}
engines: {node: '>= 16'}
'@applitools/core-base@1.22.1':
resolution: {integrity: sha512-5pHJgSjD6sGpWGrNzQsHasqkO8ROQ65z1F/dE+pITFfanreyoSrr8FLwwjQMiLq/Ggryt69PoAPXd7/N8vf0vg==}
'@applitools/core-base@1.26.0':
resolution: {integrity: sha512-7cPZTvD2cOsMF2ECEr8wtXFnGz7ihAO50Y6kEr4lyTnsPqzG3RneRF1N0IPC4/Pst0LVnIirarVr0cNnSH2ufw==}
engines: {node: '>=12.13.0'}
'@applitools/core@4.31.2':
resolution: {integrity: sha512-Na/VOO1ab3Ne+BIbX8JQWflFPj5OkhOgTia9xoXq7B4z3BoVY/37eXl3wzbVn0uQJqVuvwhe2MfCwnQ7dI2eaA==}
'@applitools/core@4.43.0':
resolution: {integrity: sha512-ylYGSJqgw8JDZBIis3yO4/Yf6tz/xQsJzKQFpMsWc2kec6OsqufGSy9tnbKE4NdJ0Z+Q1d+VeivtbYHxwRFgCQ==}
engines: {node: '>=12.13.0'}
hasBin: true
@@ -676,24 +676,24 @@ packages:
resolution: {integrity: sha512-rH3aq/dkTweEUgS/MKuthD79CZDqpQVJlqmxqVxLZVAzbeFxYdTG/gnfG0zj6YJ025jzcPH2ktdW16Rl3QLutg==}
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
'@applitools/dom-capture@11.5.4':
resolution: {integrity: sha512-3n2wLLsXpGGiYrSkHnwgFsTXZntvw5MXtt6n0Kbpyi3mqBgdZ3yPt/9tJ+pQZDX/xe9mNXUVClHXmWmVCrGPCA==}
'@applitools/dom-capture@11.5.6':
resolution: {integrity: sha512-UBf2PFLk3+tv8GnBNn6bdrp+XDX3Mx3ZckEX8njQiv1l+1WawHoxtr9JxiGk0pNZGcbZ3fv9iZ97wVWhB9wOFw==}
engines: {node: '>=12.13.0'}
'@applitools/dom-shared@1.0.16':
resolution: {integrity: sha512-P0JA5mq1f8rIi/xbh2+gCsEvv1CGenf0sGrC2UxXjmaFRpgoVS9BfpNg5aZyFJ9OPoi4qRMi9LCGsFiqZNNcTQ==}
engines: {node: '>=12.13.0'}
'@applitools/dom-snapshot@4.11.15':
resolution: {integrity: sha512-JsJ/2vTOywsxcwUMe9inGkHTBpMrnI09bCB7SJGRlbM4au4JAtMsyF5WnrbvrMlxr/kbe/BsJUDndswlkM9Duw==}
'@applitools/dom-snapshot@4.12.1':
resolution: {integrity: sha512-5zKM9xQ1v/lmKPAjk4ENT5VCshvFKxziVecS3MGZt1jQUgRlPWQPNxGp7/nKvvWhz9FabVPkmD7zzxl1nIJEzA==}
engines: {node: '>=12.13.0'}
'@applitools/driver@1.20.4':
resolution: {integrity: sha512-Lm1x6Bw66nqu7xtzRQoC3+DQb1PjZiC1DiyXi7L0YzR2c/JhQCyZ1uWWb8NrrLKctwv3SgohXZMaV90TIpAdQw==}
'@applitools/driver@1.22.1':
resolution: {integrity: sha512-TEq20ZGKCI3Ot5jsJt5Fca1RT0H0hcfFg4f2RxYkm063wUBvawgk08qkGiPZFSCSh0FtakA7J2zThDf72JzYvg==}
engines: {node: '>=12.13.0'}
'@applitools/ec-client@1.10.4':
resolution: {integrity: sha512-2+cs6jHG4HjG3UsswgIQOnjvMg7h/Ms7eerN5vkSXg0UE3/eqWaPz0VBv9+ihOHQOZwJX4BDBR791ZTsMG3XGw==}
'@applitools/ec-client@1.11.1':
resolution: {integrity: sha512-Lzj02NO4qIMuVWg/oT6ajQIVXrJKGSKjL3V/h/4wSlO+Mj0vOhPL+DepiPz/xIB+dQr0VxdWkQQ/E7zYNmsmIw==}
engines: {node: '>=12.13.0'}
hasBin: true
@@ -705,18 +705,18 @@ packages:
resolution: {integrity: sha512-SjjDBFeiKspX3nHKOoSQ+l4JUiJK3xJiWAEaR8b+GuMvnGFLnrvAECHhuXXG00+LwBJM8WKmfxEe17nvZe+nhg==}
engines: {node: '>=12'}
'@applitools/execution-grid-tunnel@3.0.8':
resolution: {integrity: sha512-4S6NcpxELH4NXketD3g6VUhWDUCuwAm4F1sCZdZLpPWOSMu5QwQDYUoe6/4t5KuktTQ4K7N90NmTzQrxiFtDKA==}
'@applitools/execution-grid-tunnel@3.1.0':
resolution: {integrity: sha512-xiQK7kWgcdr23Jex70bLy0taQfjFYluiZVC8VaQ5/yYGS9PVEdfqmAsaaEtLa/VZxVnwM5d+bcSRpLVbekCXgw==}
engines: {node: '>=14.0.0'}
hasBin: true
'@applitools/eyes-cypress@3.50.2':
resolution: {integrity: sha512-K8OIylLfkcNfbkM1VJ+ouudOFtGZaNKVxSVllP7BPKskYPWBjbHE3hSOsmvzYiY6SjdPmbBGLlgO2enrbuC/0w==}
'@applitools/eyes-cypress@3.53.2':
resolution: {integrity: sha512-huqzn5BcyKbCGv9oWGurWHCupUzlCgiq3pIG9Ce1TCo0OP9iqat95nEBUUTAUT6cIM7Q1ioihDSM0GeLse0+KA==}
engines: {node: '>=12.13.0'}
hasBin: true
'@applitools/eyes@1.32.1':
resolution: {integrity: sha512-O6nKRmPTUSgt6yUlbRY8JEJOcq5Ch/yckLipgRRxBbqsL+l9f7JzZ2VCxTuwPkhjQ0tnsitWbz9QeRge5EN6yw==}
'@applitools/eyes@1.35.3':
resolution: {integrity: sha512-WFtE8asvsYMeYvbEpaWEq2KVjb4AMDK7MK4yuBx7KmmR9bHshums8hc2Wlke17i8tn+S0ibGeK9/XsDzHpPSaQ==}
engines: {node: '>=12.13.0'}
hasBin: true
@@ -724,59 +724,53 @@ packages:
resolution: {integrity: sha512-fwiF0CbeYHDEOTD/NKaFgaI8LvRcGYG2GaJJiRwcedKko16sQ8F3TK5wXfj2Ytjf+8gjwHwsEEX550z3yvDWxA==}
engines: {node: '>=8.0.0'}
'@applitools/image@1.1.16':
resolution: {integrity: sha512-vwTDcyzW7OT/PQfVFc1v2aSb48G4I4fzqmRa83wKI3YKt4HzuYYkzFS9OcoN8pSdQ5Kt8+if5gSfSxnYDhtZbw==}
'@applitools/image@1.1.21':
resolution: {integrity: sha512-BWdSF1bET1ud0dYlvmS5zFRlHPWu5J2uTHsVgrWV3u58Kyqxy755UD4op3+kfDczALylq7wxPOIeK6zQXgiXFg==}
engines: {node: '>=12.13.0'}
'@applitools/logger@1.1.53':
resolution: {integrity: sha512-4mlzYxc0MgM3WIxEwKqIjn9W7G7kMtQc2bFRxozViKOXypTfr72j8iODs88wcetP0GsXtplhZQ5/6aZN5WY9ug==}
'@applitools/logger@2.1.5':
resolution: {integrity: sha512-HqvQY6QbYzgwwivA8044Yz4ioxlyDCcXd0YXytGNXWn3WAD/VPBju68UTW0W7g3qi2sJmcqxfZIgvOrVtat1YQ==}
engines: {node: '>=12.13.0'}
'@applitools/logger@2.1.0':
resolution: {integrity: sha512-/7wYHRyte8ZoUNGis3lVeEjBdRHda2AcykOr4+3RM2TB8APO4qIPjDSEE5TDramUKzjKC+K4BSUAL39pn8w13w==}
'@applitools/nml-client@1.10.0':
resolution: {integrity: sha512-PpwJ9/QbBlfVw8mjHu7YjngFD9L+2XL7PHFeQqMRlDFlUBiTUBmGcfm9EEGJpYiFdgo8Uh91gl6I1j1kQiq5nw==}
engines: {node: '>=12.13.0'}
peerDependencies:
'@applitools/core-base': 1.26.0
'@applitools/nml-client@1.8.24':
resolution: {integrity: sha512-BV6qONX/2FmFr2j2vRAK3F4irRvVwzYfoklpNataRSSK5ZW6Q+XVSI2uHjD1vVce4Haq7ECeVUkUFMpff1zkjw==}
engines: {node: '>=12.13.0'}
'@applitools/req@1.7.7':
resolution: {integrity: sha512-kqEu6TKdPe++53/QDOVWmqYqd2jZ0zoZ/FPPsPKvcHzIY4DFx0W/BhLl0KYXFYWKdE1slnkyyQfCqhKOP0umWw==}
'@applitools/req@1.7.15':
resolution: {integrity: sha512-P+/xvjPIQ5BUN2DSECZR/4AVZQ+8qIyokzqj4Cd1xwMdEnIWvtRCmIDRusksuSn2fqOnnTuRYab7Rb+pYZx3uw==}
engines: {node: '>=16.13.0'}
'@applitools/screenshoter@3.10.5':
resolution: {integrity: sha512-eeWae+HSUd/+J8pU0B7QdINR21sF/NHKEXW9duyOHd+GiGNsZxoWJGq1lVXxVx5QKfyrc87Gbbt3b5O+WOyIYg==}
'@applitools/screenshoter@3.11.7':
resolution: {integrity: sha512-Jkz9I4gLqb9hqn28HpKUhY4FWKmrQD0jlfd0WvkFMtdRJAgRIm1WR3yKYg68pcvP3/S0avhoWCREUSwr7zEm5g==}
engines: {node: '>=12.13.0'}
'@applitools/snippets@2.6.4':
resolution: {integrity: sha512-J9X2uqtt1LQNJsQy9X+1smXKlalKpLJpNRAIvepqGZaVOwG5eKxF7chMZSiztv2jVbZCJj7DRLZdfEueB7xjcA==}
'@applitools/snippets@2.6.5':
resolution: {integrity: sha512-sfWOKkJ4sBnlTMLKlXy308EnFbetp2Cg0Rlop21VPs+Mi5sPiln+6LX9VvRt+qNd5Q0xTavDXCUYMK2b5k4mOg==}
engines: {node: '>=12.13.0'}
'@applitools/socket@1.2.1':
resolution: {integrity: sha512-OGMVkfOQBrJviVc1K4+kZMExMBTAMA5ZtF7DGrn7pqJQTAVTI7VL9ZXUELwiburMJS6ILNXOcBvi4z9l9adCig==}
'@applitools/socket@1.2.6':
resolution: {integrity: sha512-HVVlBc7auN89Q1QWFSTIX/b46W+nnbVwBk8ho5tfJRhEFnsASGPReJgLUFfQGJK6AFyMW5i3PVcT/GB+9nmiaA==}
engines: {node: '>=12.13.0'}
'@applitools/spec-driver-webdriver@1.1.25':
resolution: {integrity: sha512-grS0B/ityKqjCac2vJSVpvFnLyyRp5KODXxOQBjmPUGDeOd/aPrw+vdXdbEJOvMZV0oyOMenFLTJ6kT2WxgPMw==}
'@applitools/spec-driver-webdriver@1.3.1':
resolution: {integrity: sha512-mAovixfnAvgWzCzy4aPoidXYhr7uWbFZ19KFiokCkhi/e9Z0lDBAXphJzR+0XIm2VCJCQpamiXJQgQisemNRZA==}
engines: {node: '>=12.13.0'}
peerDependencies:
webdriver: '>=6.0.0'
'@applitools/tunnel-client@1.6.2':
resolution: {integrity: sha512-TZrb3ctsGnA2Pd4vF2GrOyzJJf5cX16LtJmrgKL+OfdMNJLKTPZ8PrUXElpjUcaYdjdE8bXpF+afmsWfwymqiQ==}
'@applitools/tunnel-client@1.9.1':
resolution: {integrity: sha512-PXm5kCJp4xVhcRkiP5c0riHCl2KygWgldOMYy3yozcU9uxdDq2L0CociuvNvDSblmvVheFEl8kvqKZw44E6Bng==}
engines: {node: '>=12.13.0'}
hasBin: true
'@applitools/ufg-client@1.16.4':
resolution: {integrity: sha512-TTZEH3QW0EoTmgayrF8i+p3BXbqN/yfYDCQOrwwNPlGAvMNbPgfHYhZKiAOi4ecY5MwMLMxkOqTQ0MKS41wN7w==}
'@applitools/ufg-client@1.16.14':
resolution: {integrity: sha512-ivGGkovgZl0a/XWbdXzSB/diuk2rohxebUmpaknd5tm5Gf4Q0aZywKoemzJCSIqA6UWm+hAtFq/13cYe6R1nNw==}
engines: {node: '>=12.13.0'}
'@applitools/utils@1.3.36':
resolution: {integrity: sha512-eROEssh7wIW+V87PvLiHI2hUPxqoBxXFMRx3+z5qOZqXUPSR1Uz7EMFwxZcDDR7T6C3O3UDckB2aVB5fJAg5JA==}
engines: {node: '>=12.13.0'}
'@applitools/utils@1.7.7':
resolution: {integrity: sha512-4YQc/FGYmA4Jx8vRNRI6YOE8oa7tOWhCik3b1OV3RQ6OkAY5EpVRF8ruiFpX+9BIjZ2V5AdVpsJacYOIiCHNMg==}
'@applitools/utils@1.9.0':
resolution: {integrity: sha512-DGfeabHlPLFUkuxwdMEobI2FMQjX5OF+wpU6E9wmUB5zPUAdq9LvwGMvDZ1pQU9y87aZUraXp7cTFJTM6I7QUg==}
engines: {node: '>=12.13.0'}
'@argos-ci/api-client@0.8.1':
@@ -5197,15 +5191,6 @@ packages:
supports-color:
optional: true
debug@4.3.3:
resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
debug@4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
@@ -8996,6 +8981,7 @@ packages:
source-map@0.8.0-beta.0:
resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==}
engines: {node: '>= 8'}
deprecated: The work that was done in this beta branch won't be included in future versions
sourcemap-codec@1.4.8:
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
@@ -10518,38 +10504,39 @@ snapshots:
'@types/json-schema': 7.0.15
js-yaml: 4.1.0
'@applitools/core-base@1.22.1':
'@applitools/core-base@1.26.0':
dependencies:
'@applitools/image': 1.1.16
'@applitools/logger': 2.1.0
'@applitools/req': 1.7.7
'@applitools/utils': 1.7.7
'@applitools/image': 1.1.21
'@applitools/logger': 2.1.5
'@applitools/req': 1.7.15
'@applitools/utils': 1.9.0
abort-controller: 3.0.0
throat: 6.0.2
transitivePeerDependencies:
- supports-color
'@applitools/core@4.31.2(encoding@0.1.13)(typescript@5.7.3)':
'@applitools/core@4.43.0(encoding@0.1.13)(typescript@5.7.3)':
dependencies:
'@applitools/core-base': 1.22.1
'@applitools/dom-capture': 11.5.4
'@applitools/dom-snapshot': 4.11.15
'@applitools/driver': 1.20.4
'@applitools/ec-client': 1.10.4(typescript@5.7.3)
'@applitools/logger': 2.1.0
'@applitools/nml-client': 1.8.24
'@applitools/req': 1.7.7
'@applitools/screenshoter': 3.10.5
'@applitools/snippets': 2.6.4
'@applitools/socket': 1.2.1
'@applitools/spec-driver-webdriver': 1.1.25(webdriver@7.31.1(typescript@5.7.3))
'@applitools/ufg-client': 1.16.4
'@applitools/utils': 1.7.7
'@applitools/core-base': 1.26.0
'@applitools/dom-capture': 11.5.6
'@applitools/dom-snapshot': 4.12.1
'@applitools/driver': 1.22.1
'@applitools/ec-client': 1.11.1(typescript@5.7.3)
'@applitools/logger': 2.1.5
'@applitools/nml-client': 1.10.0(@applitools/core-base@1.26.0)
'@applitools/req': 1.7.15
'@applitools/screenshoter': 3.11.7
'@applitools/snippets': 2.6.5
'@applitools/socket': 1.2.6
'@applitools/spec-driver-webdriver': 1.3.1(webdriver@7.31.1(typescript@5.7.3))
'@applitools/ufg-client': 1.16.14
'@applitools/utils': 1.9.0
'@types/ws': 8.5.5
abort-controller: 3.0.0
chalk: 4.1.2
node-fetch: 2.6.7(encoding@0.1.13)
semver: 7.6.2
throat: 6.0.2
webdriver: 7.31.1(typescript@5.7.3)
ws: 8.17.1
yargs: 17.7.2
@@ -10565,39 +10552,39 @@ snapshots:
mdn-data: 2.1.0
source-map-js: 1.0.1
'@applitools/dom-capture@11.5.4':
'@applitools/dom-capture@11.5.6':
dependencies:
'@applitools/dom-shared': 1.0.16
'@applitools/functional-commons': 1.6.0
'@applitools/dom-shared@1.0.16': {}
'@applitools/dom-snapshot@4.11.15':
'@applitools/dom-snapshot@4.12.1':
dependencies:
'@applitools/css-tree': 1.1.4
'@applitools/dom-shared': 1.0.16
'@applitools/functional-commons': 1.6.0
pako: 1.0.11
'@applitools/driver@1.20.4':
'@applitools/driver@1.22.1':
dependencies:
'@applitools/logger': 2.1.0
'@applitools/snippets': 2.6.4
'@applitools/utils': 1.7.7
'@applitools/logger': 2.1.5
'@applitools/snippets': 2.6.5
'@applitools/utils': 1.9.0
semver: 7.6.2
transitivePeerDependencies:
- supports-color
'@applitools/ec-client@1.10.4(typescript@5.7.3)':
'@applitools/ec-client@1.11.1(typescript@5.7.3)':
dependencies:
'@applitools/core-base': 1.22.1
'@applitools/driver': 1.20.4
'@applitools/logger': 2.1.0
'@applitools/req': 1.7.7
'@applitools/socket': 1.2.1
'@applitools/spec-driver-webdriver': 1.1.25(webdriver@7.31.1(typescript@5.7.3))
'@applitools/tunnel-client': 1.6.2
'@applitools/utils': 1.7.7
'@applitools/core-base': 1.26.0
'@applitools/driver': 1.22.1
'@applitools/logger': 2.1.5
'@applitools/req': 1.7.15
'@applitools/socket': 1.2.6
'@applitools/spec-driver-webdriver': 1.3.1(webdriver@7.31.1(typescript@5.7.3))
'@applitools/tunnel-client': 1.9.1
'@applitools/utils': 1.9.0
abort-controller: 3.0.0
webdriver: 7.31.1(typescript@5.7.3)
yargs: 17.7.2
@@ -10612,11 +10599,11 @@ snapshots:
binary: 0.3.0
is-localhost-ip: 2.0.0
'@applitools/execution-grid-tunnel@3.0.8':
'@applitools/execution-grid-tunnel@3.1.0':
dependencies:
'@applitools/eg-frpc': 1.0.5
'@applitools/eg-socks5-proxy-server': 0.5.6
'@applitools/logger': 1.1.53
'@applitools/logger': 2.1.5
dotenv: 16.4.7
encoding: 0.1.13
fastify: 4.29.0
@@ -10631,13 +10618,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@applitools/eyes-cypress@3.50.2(encoding@0.1.13)(typescript@5.7.3)':
'@applitools/eyes-cypress@3.53.2(encoding@0.1.13)(typescript@5.7.3)':
dependencies:
'@applitools/core': 4.31.2(encoding@0.1.13)(typescript@5.7.3)
'@applitools/eyes': 1.32.1(encoding@0.1.13)(typescript@5.7.3)
'@applitools/core': 4.43.0(encoding@0.1.13)(typescript@5.7.3)
'@applitools/eyes': 1.35.3(encoding@0.1.13)(typescript@5.7.3)
'@applitools/functional-commons': 1.6.0
'@applitools/logger': 2.1.0
'@applitools/utils': 1.7.7
'@applitools/logger': 2.1.5
'@applitools/utils': 1.9.0
boxen: 5.1.2
chalk: 3.0.0
semver: 7.6.2
@@ -10650,12 +10637,13 @@ snapshots:
- typescript
- utf-8-validate
'@applitools/eyes@1.32.1(encoding@0.1.13)(typescript@5.7.3)':
'@applitools/eyes@1.35.3(encoding@0.1.13)(typescript@5.7.3)':
dependencies:
'@applitools/core': 4.31.2(encoding@0.1.13)(typescript@5.7.3)
'@applitools/logger': 2.1.0
'@applitools/utils': 1.7.7
'@applitools/core': 4.43.0(encoding@0.1.13)(typescript@5.7.3)
'@applitools/logger': 2.1.5
'@applitools/utils': 1.9.0
chalk: 4.1.2
yargs: 17.7.2
transitivePeerDependencies:
- bufferutil
- encoding
@@ -10665,41 +10653,34 @@ snapshots:
'@applitools/functional-commons@1.6.0': {}
'@applitools/image@1.1.16':
'@applitools/image@1.1.21':
dependencies:
'@applitools/utils': 1.7.7
'@applitools/utils': 1.9.0
bmpimagejs: 1.0.4
jpeg-js: 0.4.4
omggif: 1.0.10
png-async: 0.9.4
'@applitools/logger@1.1.53':
'@applitools/logger@2.1.5':
dependencies:
'@applitools/utils': 1.3.36
chalk: 4.1.2
debug: 4.3.3
transitivePeerDependencies:
- supports-color
'@applitools/logger@2.1.0':
dependencies:
'@applitools/utils': 1.7.7
'@applitools/utils': 1.9.0
chalk: 4.1.2
debug: 4.3.4
transitivePeerDependencies:
- supports-color
'@applitools/nml-client@1.8.24':
'@applitools/nml-client@1.10.0(@applitools/core-base@1.26.0)':
dependencies:
'@applitools/logger': 2.1.0
'@applitools/req': 1.7.7
'@applitools/utils': 1.7.7
'@applitools/core-base': 1.26.0
'@applitools/logger': 2.1.5
'@applitools/req': 1.7.15
'@applitools/utils': 1.9.0
transitivePeerDependencies:
- supports-color
'@applitools/req@1.7.7':
'@applitools/req@1.7.15':
dependencies:
'@applitools/utils': 1.7.7
'@applitools/utils': 1.9.0
abort-controller: 3.0.0
http-proxy-agent: 5.0.0
https-proxy-agent: 5.0.1
@@ -10707,62 +10688,60 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@applitools/screenshoter@3.10.5':
'@applitools/screenshoter@3.11.7':
dependencies:
'@applitools/image': 1.1.16
'@applitools/logger': 2.1.0
'@applitools/snippets': 2.6.4
'@applitools/utils': 1.7.7
'@applitools/image': 1.1.21
'@applitools/logger': 2.1.5
'@applitools/snippets': 2.6.5
'@applitools/utils': 1.9.0
transitivePeerDependencies:
- supports-color
'@applitools/snippets@2.6.4': {}
'@applitools/snippets@2.6.5': {}
'@applitools/socket@1.2.1':
'@applitools/socket@1.2.6':
dependencies:
'@applitools/logger': 2.1.0
'@applitools/utils': 1.7.7
'@applitools/logger': 2.1.5
'@applitools/utils': 1.9.0
transitivePeerDependencies:
- supports-color
'@applitools/spec-driver-webdriver@1.1.25(webdriver@7.31.1(typescript@5.7.3))':
'@applitools/spec-driver-webdriver@1.3.1(webdriver@7.31.1(typescript@5.7.3))':
dependencies:
'@applitools/driver': 1.20.4
'@applitools/utils': 1.7.7
'@applitools/driver': 1.22.1
'@applitools/utils': 1.9.0
http-proxy-agent: 5.0.0
https-proxy-agent: 5.0.1
webdriver: 7.31.1(typescript@5.7.3)
transitivePeerDependencies:
- supports-color
'@applitools/tunnel-client@1.6.2':
'@applitools/tunnel-client@1.9.1':
dependencies:
'@applitools/execution-grid-tunnel': 3.0.8
'@applitools/logger': 2.1.0
'@applitools/req': 1.7.7
'@applitools/socket': 1.2.1
'@applitools/utils': 1.7.7
'@applitools/execution-grid-tunnel': 3.1.0
'@applitools/logger': 2.1.5
'@applitools/req': 1.7.15
'@applitools/socket': 1.2.6
'@applitools/utils': 1.9.0
abort-controller: 3.0.0
yargs: 17.7.2
transitivePeerDependencies:
- supports-color
'@applitools/ufg-client@1.16.4':
'@applitools/ufg-client@1.16.14':
dependencies:
'@applitools/css-tree': 1.1.4
'@applitools/image': 1.1.16
'@applitools/logger': 2.1.0
'@applitools/req': 1.7.7
'@applitools/utils': 1.7.7
'@applitools/image': 1.1.21
'@applitools/logger': 2.1.5
'@applitools/req': 1.7.15
'@applitools/utils': 1.9.0
'@xmldom/xmldom': 0.8.10
abort-controller: 3.0.0
throat: 6.0.2
transitivePeerDependencies:
- supports-color
'@applitools/utils@1.3.36': {}
'@applitools/utils@1.7.7': {}
'@applitools/utils@1.9.0': {}
'@argos-ci/api-client@0.8.1':
dependencies:
@@ -12142,7 +12121,7 @@ snapshots:
outdent: 0.5.0
prettier: 2.8.8
resolve-from: 5.0.0
semver: 7.7.1
semver: 7.7.2
'@changesets/assemble-release-plan@6.0.6':
dependencies:
@@ -12151,7 +12130,7 @@ snapshots:
'@changesets/should-skip-package': 0.1.2
'@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
semver: 7.7.1
semver: 7.7.2
'@changesets/changelog-git@0.2.1':
dependencies:
@@ -12215,7 +12194,7 @@ snapshots:
'@changesets/types': 6.1.0
'@manypkg/get-packages': 1.1.3
picocolors: 1.1.1
semver: 7.7.1
semver: 7.7.2
'@changesets/get-github-info@0.6.0(encoding@0.1.13)':
dependencies:
@@ -12673,7 +12652,7 @@ snapshots:
'@babel/preset-env': 7.27.2(@babel/core@7.27.1)
babel-loader: 9.2.1(@babel/core@7.27.1)(webpack@5.95.0(esbuild@0.25.0))
bluebird: 3.7.1
debug: 4.4.0
debug: 4.4.1(supports-color@8.1.1)
lodash: 4.17.21
webpack: 5.95.0(esbuild@0.25.0)
transitivePeerDependencies:
@@ -16353,10 +16332,6 @@ snapshots:
optionalDependencies:
supports-color: 8.1.1
debug@4.3.3:
dependencies:
ms: 2.1.2
debug@4.3.4:
dependencies:
ms: 2.1.2
@@ -17402,7 +17377,7 @@ snapshots:
'@actions/core': 1.11.1
arg: 5.0.2
console.table: 0.10.0
debug: 4.4.0
debug: 4.4.1(supports-color@8.1.1)
find-test-names: 1.29.5(@babel/core@7.27.1)
globby: 11.1.0
minimatch: 3.1.2
@@ -18303,7 +18278,7 @@ snapshots:
istanbul-lib-source-maps@5.0.6:
dependencies:
'@jridgewell/trace-mapping': 0.3.25
debug: 4.4.0
debug: 4.4.1(supports-color@8.1.1)
istanbul-lib-coverage: 3.2.2
transitivePeerDependencies:
- supports-color
@@ -21298,7 +21273,7 @@ snapshots:
teen_process@1.16.0:
dependencies:
'@babel/runtime': 7.26.9
'@babel/runtime': 7.27.1
bluebird: 3.7.2
lodash: 4.17.21
shell-quote: 1.8.2

View File

@@ -18,6 +18,7 @@
"./demos/dev",
"./vite.config.ts",
"./vitest.workspace.js",
"eslint.config.js"
"eslint.config.js",
"./appli.config.ts"
]
}