Compare commits

..

10 Commits

Author SHA1 Message Date
omkarht
bf50ce5237 fix: handle uncaught exceptions in Gantt chart rendering test for invalid dates
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-11-26 18:59:18 +05:30
omkarht
8bfd47758a chore: add changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-11-26 17:30:00 +05:30
omkarht
88fd141276 fix: correct Gantt diagram dateFormat syntax in test case
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-11-26 15:46:59 +05:30
omkarht
454238867b chore: add tests for handling invalid and non-standard date formats in ganttDb
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-11-26 13:55:00 +05:30
omkarht
6025ec663c 5496 : fixed UI crash from excessive tick generation with invalid dates/intervals
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-11-26 13:39:22 +05:30
Alois Klink
2346801c30 Merge pull request #7188 from kimulaco/docs/7187_fix-radar-diagram-example
docs: Remove trailing comma from radar diagram example
2025-11-25 08:21:28 +00:00
Shubham P
d7eb94dc89 Merge pull request #7172 from mermaid-js/docs/correct-block-arrow-example
docs(block): correct block arrow example
2025-11-25 06:57:41 +00:00
kimulaco
e20b079707 docs(radar): remove trailing commas 2025-11-22 18:44:44 +09:00
autofix-ci[bot]
6e869ff8dc [autofix.ci] apply automated fixes 2025-11-18 08:41:51 +00:00
Alois Klink
9df18da01c docs(block): correct block arrow example
The same ID meant we were overriding the previous arrow.

Co-authored-by: jonathanpoelen <1436727+jonathanpoelen@users.noreply.github.com>
Fixes: https://github.com/mermaid-js/mermaid/issues/7159
Fixes: a0d328d734
2025-11-18 17:34:36 +09:00
12 changed files with 288 additions and 166 deletions

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: validate dates and tick interval to prevent UI freeze/crash in gantt diagramtype

View File

@@ -118,6 +118,15 @@ describe('Gantt diagram', () => {
);
});
it('should FAIL rendering a gantt chart for issue #1060 with invalid date', () => {
let errorCaught = false;
cy.on('uncaught:exception', (err) => {
// Expect error related to invalid or missing date format
expect(err.message).to.include('Invalid date');
errorCaught = true;
return false; // prevent Cypress from failing the test
});
imgSnapshotTest(
`
gantt
@@ -150,12 +159,16 @@ describe('Gantt diagram', () => {
section Plasma Calls & updates
OVM :ovm, 2019-07-12, 120d
Plasma call 26 :pc26, 2019-08-21, 1d
Plasma call 27 :pc27, 2019-09-03, 1d
Plasma call 28 :pc28, 2019-09-17, 1d
`,
Plasma call 26 :pc26, 2019-08-21, 1d
Plasma call 27 :pc27, 2019-09-03, 1d
Plasma call 28 :pc28, 2019-09-17, 1d
`,
{}
);
cy.then(() => {
expect(errorCaught, 'Expected rendering to fail with invalid date error').to.equal(true);
});
});
it('should default to showing today marker', () => {

View File

@@ -286,9 +286,9 @@ erDiagram
accTitle: This is a title
accDescr: This is a description
dateFormat :YYYY-MM-DD
dateFormat YYYY-MM-DD
title :Adding GANTT diagram functionality to mermaid
excludes :excludes the named dates/days from being included in a charted task..
excludes :excludes the named dates/days from being included in a charted task.
section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d

View File

@@ -402,7 +402,7 @@ block
blockArrowId4<["Label"]>(down)
blockArrowId5<["Label"]>(x)
blockArrowId6<["Label"]>(y)
blockArrowId6<["Label"]>(x, down)
blockArrowId7<["Label"]>(x, down)
```
```mermaid
@@ -413,7 +413,7 @@ block
blockArrowId4<["Label"]>(down)
blockArrowId5<["Label"]>(x)
blockArrowId6<["Label"]>(y)
blockArrowId6<["Label"]>(x, down)
blockArrowId7<["Label"]>(x, down)
```
#### Example - Space Blocks

View File

@@ -62,7 +62,7 @@ radar-beta
radar-beta
title Restaurant Comparison
axis food["Food Quality"], service["Service"], price["Price"]
axis ambiance["Ambiance"],
axis ambiance["Ambiance"]
curve a["Restaurant A"]{4, 3, 2, 4}
curve b["Restaurant B"]{3, 4, 3, 3}
@@ -78,7 +78,7 @@ radar-beta
radar-beta
title Restaurant Comparison
axis food["Food Quality"], service["Service"], price["Price"]
axis ambiance["Ambiance"],
axis ambiance["Ambiance"]
curve a["Restaurant A"]{4, 3, 2, 4}
curve b["Restaurant B"]{3, 4, 3, 3}

View File

@@ -300,6 +300,16 @@ const getStartDate = function (prevTime, dateFormat, str) {
} else {
log.debug('Invalid date:' + str);
log.debug('With date format:' + dateFormat.trim());
// Only allow fallback for formats that are simple timestamps (x, X)
// which represent Unix timestamps. For all other formats, if dayjs
// strict parsing fails - throws an error.
const isTimestampFormat = dateFormat.trim() === 'x' || dateFormat.trim() === 'X';
if (!isTimestampFormat) {
throw new Error(`Invalid date: "${str}" does not match format "${dateFormat.trim()}".`);
}
const d = new Date(str);
if (
d === undefined ||

View File

@@ -503,6 +503,51 @@ describe('when using the ganttDb', function () {
it('should reject dates with ridiculous years', function () {
ganttDb.setDateFormat('YYYYMMDD');
ganttDb.addTask('test1', 'id1,202304,1d');
expect(() => ganttDb.getTasks()).toThrowError('Invalid date:202304');
expect(() => ganttDb.getTasks()).toThrowError(/Invalid date/);
});
describe('when using non-standard date formats (issue #5496)', function () {
it('should reject invalid dates when using seconds-only format', function () {
ganttDb.setDateFormat('ss');
ganttDb.addTask('RTT', 'rtt, 0, 20');
expect(() => ganttDb.getTasks()).toThrowError(/Invalid date/);
});
it('should reject invalid dates when using time-only formats without year', function () {
// Formats without year info should not fall back to new Date()
ganttDb.setDateFormat('HH:mm');
ganttDb.addTask('test', 'id1, invalid_date, 1h');
expect(() => ganttDb.getTasks()).toThrowError(/Invalid date/);
});
it('should allow valid seconds-only format when date matches', function () {
// Valid case - the date format 'ss' should work when the value is valid
ganttDb.setDateFormat('ss');
ganttDb.addTask('Task', 'task1, 00, 6s');
// This should not throw - 00 is a valid 'ss' value
const tasks = ganttDb.getTasks();
expect(tasks).toHaveLength(1);
});
it('should reject dates with typos in year like 202-12-01 instead of 2024-12-01', function () {
ganttDb.setDateFormat('YYYY-MM-DD');
ganttDb.addSection('Vacation');
ganttDb.addTask('London', '2024-12-01, 7d');
ganttDb.addTask('London', '202-12-01, 7d');
expect(() => ganttDb.getTasks()).toThrowError(/Invalid date/);
});
it('should work correctly with valid YYYY-MM-DD dates', function () {
// Valid case - both dates are correctly formatted
ganttDb.setDateFormat('YYYY-MM-DD');
ganttDb.addSection('Vacation');
ganttDb.addTask('London Trip 1', '2024-12-01, 7d');
ganttDb.addTask('London Trip 2', '2024-12-15, 7d');
const tasks = ganttDb.getTasks();
expect(tasks).toHaveLength(2);
// Verify years are correct (2024)
expect(tasks[0].startTime.getFullYear()).toBe(2024);
expect(tasks[1].startTime.getFullYear()).toBe(2024);
});
});
});

View File

@@ -78,6 +78,7 @@ const getMaxIntersections = (tasks, orderOffset) => {
};
let w;
const MAX_TICK_COUNT = 10000;
export const draw = function (text, id, version, diagObj) {
const conf = getConfig().gantt;
@@ -602,6 +603,30 @@ export const draw = function (text, id, version, diagObj) {
.attr('class', 'exclude-range');
}
/**
* Calculates the estimated number of ticks based on the time domain and tick interval.
* Returns the count or Infinity if there would be too many ticks.
* @param {Date} minTime - The minimum time in the domain
* @param {Date} maxTime - The maximum time in the domain
* @param {number} every - The interval count (e.g., 1 for "1second")
* @param {string} interval - The interval unit (e.g., "second", "day")
* @returns {number} The estimated number of ticks
*/
function getEstimatedTickCount(minTime, maxTime, every, interval) {
const timeDiffMs = maxTime - minTime;
const msPerUnit = {
millisecond: 1,
second: 1000,
minute: 60 * 1000,
hour: 60 * 60 * 1000,
day: 24 * 60 * 60 * 1000,
week: 7 * 24 * 60 * 60 * 1000,
month: 30 * 24 * 60 * 60 * 1000, // Approximate
};
const intervalMs = (msPerUnit[interval] || msPerUnit.day) * every;
return Math.ceil(timeDiffMs / intervalMs);
}
/**
* @param theSidePad
* @param theTopPad
@@ -630,32 +655,47 @@ export const draw = function (text, id, version, diagObj) {
);
if (resultTickInterval !== null) {
const every = resultTickInterval[1];
const every = parseInt(resultTickInterval[1], 10);
const interval = resultTickInterval[2];
const weekday = diagObj.db.getWeekday() || conf.weekday;
switch (interval) {
case 'millisecond':
bottomXAxis.ticks(timeMillisecond.every(every));
break;
case 'second':
bottomXAxis.ticks(timeSecond.every(every));
break;
case 'minute':
bottomXAxis.ticks(timeMinute.every(every));
break;
case 'hour':
bottomXAxis.ticks(timeHour.every(every));
break;
case 'day':
bottomXAxis.ticks(timeDay.every(every));
break;
case 'week':
bottomXAxis.ticks(mapWeekdayToTimeFunction[weekday].every(every));
break;
case 'month':
bottomXAxis.ticks(timeMonth.every(every));
break;
// Get the time domain to check tick count
const domain = timeScale.domain();
const minTime = domain[0];
const maxTime = domain[1];
const estimatedTicks = getEstimatedTickCount(minTime, maxTime, every, interval);
if (estimatedTicks > MAX_TICK_COUNT) {
log.warn(
`The tick interval "${every}${interval}" would generate ${estimatedTicks} ticks, ` +
`which exceeds the maximum allowed (${MAX_TICK_COUNT}). ` +
`This may indicate an invalid date or time range. Skipping custom tick interval.`
);
// D3 using its default automatic tick generation
} else {
switch (interval) {
case 'millisecond':
bottomXAxis.ticks(timeMillisecond.every(every));
break;
case 'second':
bottomXAxis.ticks(timeSecond.every(every));
break;
case 'minute':
bottomXAxis.ticks(timeMinute.every(every));
break;
case 'hour':
bottomXAxis.ticks(timeHour.every(every));
break;
case 'day':
bottomXAxis.ticks(timeDay.every(every));
break;
case 'week':
bottomXAxis.ticks(mapWeekdayToTimeFunction[weekday].every(every));
break;
case 'month':
bottomXAxis.ticks(timeMonth.every(every));
break;
}
}
}
@@ -677,32 +717,41 @@ export const draw = function (text, id, version, diagObj) {
.tickFormat(timeFormat(axisFormat));
if (resultTickInterval !== null) {
const every = resultTickInterval[1];
const every = parseInt(resultTickInterval[1], 10);
const interval = resultTickInterval[2];
const weekday = diagObj.db.getWeekday() || conf.weekday;
switch (interval) {
case 'millisecond':
topXAxis.ticks(timeMillisecond.every(every));
break;
case 'second':
topXAxis.ticks(timeSecond.every(every));
break;
case 'minute':
topXAxis.ticks(timeMinute.every(every));
break;
case 'hour':
topXAxis.ticks(timeHour.every(every));
break;
case 'day':
topXAxis.ticks(timeDay.every(every));
break;
case 'week':
topXAxis.ticks(mapWeekdayToTimeFunction[weekday].every(every));
break;
case 'month':
topXAxis.ticks(timeMonth.every(every));
break;
// Get the time domain to check tick count
const domain = timeScale.domain();
const minTime = domain[0];
const maxTime = domain[1];
const estimatedTicks = getEstimatedTickCount(minTime, maxTime, every, interval);
// Only apply custom ticks if the count is reasonable
if (estimatedTicks <= MAX_TICK_COUNT) {
switch (interval) {
case 'millisecond':
topXAxis.ticks(timeMillisecond.every(every));
break;
case 'second':
topXAxis.ticks(timeSecond.every(every));
break;
case 'minute':
topXAxis.ticks(timeMinute.every(every));
break;
case 'hour':
topXAxis.ticks(timeHour.every(every));
break;
case 'day':
topXAxis.ticks(timeDay.every(every));
break;
case 'week':
topXAxis.ticks(mapWeekdayToTimeFunction[weekday].every(every));
break;
case 'month':
topXAxis.ticks(timeMonth.every(every));
break;
}
}
}

View File

@@ -21,7 +21,7 @@
"font-awesome": "^4.7.0",
"jiti": "^2.4.2",
"mermaid": "workspace:^",
"vue": "^3.5.25"
"vue": "^3.5.24"
},
"devDependencies": {
"@iconify-json/carbon": "^1.2.14",

View File

@@ -283,7 +283,7 @@ block
blockArrowId4<["Label"]>(down)
blockArrowId5<["Label"]>(x)
blockArrowId6<["Label"]>(y)
blockArrowId6<["Label"]>(x, down)
blockArrowId7<["Label"]>(x, down)
```
#### Example - Space Blocks

View File

@@ -42,7 +42,7 @@ radar-beta
radar-beta
title Restaurant Comparison
axis food["Food Quality"], service["Service"], price["Price"]
axis ambiance["Ambiance"],
axis ambiance["Ambiance"]
curve a["Restaurant A"]{4, 3, 2, 4}
curve b["Restaurant B"]{3, 4, 3, 3}

212
pnpm-lock.yaml generated
View File

@@ -479,7 +479,7 @@ importers:
version: 7.4.47
'@vueuse/core':
specifier: ^13.9.0
version: 13.9.0(vue@3.5.25(typescript@5.9.2))
version: 13.9.0(vue@3.5.24(typescript@5.9.2))
font-awesome:
specifier: ^4.7.0
version: 4.7.0
@@ -490,8 +490,8 @@ importers:
specifier: workspace:^
version: link:../..
vue:
specifier: ^3.5.25
version: 3.5.25(typescript@5.9.2)
specifier: ^3.5.24
version: 3.5.24(typescript@5.9.2)
devDependencies:
'@iconify-json/carbon':
specifier: ^1.2.14
@@ -504,7 +504,7 @@ importers:
version: 1.0.1(vite-plugin-pwa@1.0.3(vite@7.1.11(@types/node@22.19.1)(jiti@2.5.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(workbox-build@7.3.0(@types/babel__core@7.20.5))(workbox-window@7.3.0))
'@vitejs/plugin-vue':
specifier: ^6.0.2
version: 6.0.2(vite@7.1.11(@types/node@22.19.1)(jiti@2.5.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.2))
version: 6.0.2(vite@7.1.11(@types/node@22.19.1)(jiti@2.5.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.24(typescript@5.9.2))
fast-glob:
specifier: ^3.3.3
version: 3.3.3
@@ -519,7 +519,7 @@ importers:
version: 66.5.9(postcss@8.5.6)(vite@7.1.11(@types/node@22.19.1)(jiti@2.5.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))
unplugin-vue-components:
specifier: ^28.8.0
version: 28.8.0(@babel/parser@7.28.5)(vue@3.5.25(typescript@5.9.2))
version: 28.8.0(@babel/parser@7.28.5)(vue@3.5.24(typescript@5.9.2))
vite:
specifier: ^7.0.8
version: 7.1.11(@types/node@22.19.1)(jiti@2.5.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)
@@ -3705,39 +3705,39 @@ packages:
'@vue/compiler-core@3.5.21':
resolution: {integrity: sha512-8i+LZ0vf6ZgII5Z9XmUvrCyEzocvWT+TeR2VBUVlzIH6Tyv57E20mPZ1bCS+tbejgUgmjrEh7q/0F0bibskAmw==}
'@vue/compiler-core@3.5.23':
resolution: {integrity: sha512-nW7THWj5HOp085ROk65LwaoxuzDsjIxr485F4iu63BoxsXoSqKqmsUUoP4A7Gl67DgIgi0zJ8JFgHfvny/74MA==}
'@vue/compiler-core@3.5.24':
resolution: {integrity: sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig==}
'@vue/compiler-core@3.5.25':
resolution: {integrity: sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==}
'@vue/compiler-dom@3.5.21':
resolution: {integrity: sha512-jNtbu/u97wiyEBJlJ9kmdw7tAr5Vy0Aj5CgQmo+6pxWNQhXZDPsRr1UWPN4v3Zf82s2H3kF51IbzZ4jMWAgPlQ==}
'@vue/compiler-dom@3.5.23':
resolution: {integrity: sha512-AT8RMw0vEzzzO0JU5gY0F6iCzaWUIh/aaRVordzMBKXRpoTllTT4kocHDssByPsvodNCfump/Lkdow2mT/O5KQ==}
'@vue/compiler-dom@3.5.24':
resolution: {integrity: sha512-1QHGAvs53gXkWdd3ZMGYuvQFXHW4ksKWPG8HP8/2BscrbZ0brw183q2oNWjMrSWImYLHxHrx1ItBQr50I/q2zw==}
'@vue/compiler-dom@3.5.25':
resolution: {integrity: sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==}
'@vue/compiler-sfc@3.5.21':
resolution: {integrity: sha512-SXlyk6I5eUGBd2v8Ie7tF6ADHE9kCR6mBEuPyH1nUZ0h6Xx6nZI29i12sJKQmzbDyr2tUHMhhTt51Z6blbkTTQ==}
'@vue/compiler-sfc@3.5.23':
resolution: {integrity: sha512-3QTEUo4qg7FtQwaDJa8ou1CUikx5WTtZlY61rRRDu3lK2ZKrGoAGG8mvDgOpDsQ4A1bez9s+WtBB6DS2KuFCPw==}
'@vue/compiler-sfc@3.5.24':
resolution: {integrity: sha512-8EG5YPRgmTB+YxYBM3VXy8zHD9SWHUJLIGPhDovo3Z8VOgvP+O7UP5vl0J4BBPWYD9vxtBabzW1EuEZ+Cqs14g==}
'@vue/compiler-sfc@3.5.25':
resolution: {integrity: sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==}
'@vue/compiler-ssr@3.5.21':
resolution: {integrity: sha512-vKQ5olH5edFZdf5ZrlEgSO1j1DMA4u23TVK5XR1uMhvwnYvVdDF0nHXJUblL/GvzlShQbjhZZ2uvYmDlAbgo9w==}
'@vue/compiler-ssr@3.5.23':
resolution: {integrity: sha512-Hld2xphbMjXs9Q9WKxPf2EqmE+Rq/FEDnK/wUBtmYq74HCV4XDdSCheAaB823OQXIIFGq9ig/RbAZkF9s4U0Ow==}
'@vue/compiler-ssr@3.5.24':
resolution: {integrity: sha512-trOvMWNBMQ/odMRHW7Ae1CdfYx+7MuiQu62Jtu36gMLXcaoqKvAyh+P73sYG9ll+6jLB6QPovqoKGGZROzkFFg==}
'@vue/compiler-ssr@3.5.25':
resolution: {integrity: sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==}
'@vue/devtools-api@7.7.7':
resolution: {integrity: sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==}
@@ -3750,40 +3750,40 @@ packages:
'@vue/reactivity@3.5.21':
resolution: {integrity: sha512-3ah7sa+Cwr9iiYEERt9JfZKPw4A2UlbY8RbbnH2mGCE8NwHkhmlZt2VsH0oDA3P08X3jJd29ohBDtX+TbD9AsA==}
'@vue/reactivity@3.5.25':
resolution: {integrity: sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==}
'@vue/reactivity@3.5.24':
resolution: {integrity: sha512-BM8kBhtlkkbnyl4q+HiF5R5BL0ycDPfihowulm02q3WYp2vxgPcJuZO866qa/0u3idbMntKEtVNuAUp5bw4teg==}
'@vue/runtime-core@3.5.21':
resolution: {integrity: sha512-+DplQlRS4MXfIf9gfD1BOJpk5RSyGgGXD/R+cumhe8jdjUcq/qlxDawQlSI8hCKupBlvM+3eS1se5xW+SuNAwA==}
'@vue/runtime-core@3.5.25':
resolution: {integrity: sha512-Z751v203YWwYzy460bzsYQISDfPjHTl+6Zzwo/a3CsAf+0ccEjQ8c+0CdX1WsumRTHeywvyUFtW6KvNukT/smA==}
'@vue/runtime-core@3.5.24':
resolution: {integrity: sha512-RYP/byyKDgNIqfX/gNb2PB55dJmM97jc9wyF3jK7QUInYKypK2exmZMNwnjueWwGceEkP6NChd3D2ZVEp9undQ==}
'@vue/runtime-dom@3.5.21':
resolution: {integrity: sha512-3M2DZsOFwM5qI15wrMmNF5RJe1+ARijt2HM3TbzBbPSuBHOQpoidE+Pa+XEaVN+czbHf81ETRoG1ltztP2em8w==}
'@vue/runtime-dom@3.5.25':
resolution: {integrity: sha512-a4WrkYFbb19i9pjkz38zJBg8wa/rboNERq3+hRRb0dHiJh13c+6kAbgqCPfMaJ2gg4weWD3APZswASOfmKwamA==}
'@vue/runtime-dom@3.5.24':
resolution: {integrity: sha512-Z8ANhr/i0XIluonHVjbUkjvn+CyrxbXRIxR7wn7+X7xlcb7dJsfITZbkVOeJZdP8VZwfrWRsWdShH6pngMxRjw==}
'@vue/server-renderer@3.5.21':
resolution: {integrity: sha512-qr8AqgD3DJPJcGvLcJKQo2tAc8OnXRcfxhOJCPF+fcfn5bBGz7VCcO7t+qETOPxpWK1mgysXvVT/j+xWaHeMWA==}
peerDependencies:
vue: 3.5.21
'@vue/server-renderer@3.5.25':
resolution: {integrity: sha512-UJaXR54vMG61i8XNIzTSf2Q7MOqZHpp8+x3XLGtE3+fL+nQd+k7O5+X3D/uWrnQXOdMw5VPih+Uremcw+u1woQ==}
'@vue/server-renderer@3.5.24':
resolution: {integrity: sha512-Yh2j2Y4G/0/4z/xJ1Bad4mxaAk++C2v4kaa8oSYTMJBJ00/ndPuxCnWeot0/7/qafQFLh5pr6xeV6SdMcE/G1w==}
peerDependencies:
vue: 3.5.25
vue: 3.5.24
'@vue/shared@3.5.21':
resolution: {integrity: sha512-+2k1EQpnYuVuu3N7atWyG3/xoFWIVJZq4Mz8XNOdScFI0etES75fbny/oU4lKWk/577P1zmg0ioYvpGEDZ3DLw==}
'@vue/shared@3.5.23':
resolution: {integrity: sha512-0YZ1DYuC5o/YJPf6pFdt2KYxVGDxkDbH/1NYJnVJWUkzr8ituBEmFVQRNX2gCaAsFEjEDnLkWpgqlZA7htgS/g==}
'@vue/shared@3.5.24':
resolution: {integrity: sha512-9cwHL2EsJBdi8NY22pngYYWzkTDhld6fAD6jlaeloNGciNSJL6bLpbxVgXl96X00Jtc6YWQv96YA/0sxex/k1A==}
'@vue/shared@3.5.25':
resolution: {integrity: sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==}
'@vueuse/core@12.8.2':
resolution: {integrity: sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==}
@@ -9828,8 +9828,8 @@ packages:
typescript:
optional: true
vue@3.5.25:
resolution: {integrity: sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==}
vue@3.5.24:
resolution: {integrity: sha512-uTHDOpVQTMjcGgrqFPSb8iO2m1DUvo+WbGqoXQz8Y1CeBYQ0FXf2z1gLRaBtHjlRz7zZUBHxjVB5VTLzYkvftg==}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
@@ -14378,11 +14378,11 @@ snapshots:
vite: 5.4.20(@types/node@22.19.1)(terser@5.44.1)
vue: 3.5.21(typescript@5.9.2)
'@vitejs/plugin-vue@6.0.2(vite@7.1.11(@types/node@22.19.1)(jiti@2.5.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.25(typescript@5.9.2))':
'@vitejs/plugin-vue@6.0.2(vite@7.1.11(@types/node@22.19.1)(jiti@2.5.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.24(typescript@5.9.2))':
dependencies:
'@rolldown/pluginutils': 1.0.0-beta.50
vite: 7.1.11(@types/node@22.19.1)(jiti@2.5.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)
vue: 3.5.25(typescript@5.9.2)
vue: 3.5.24(typescript@5.9.2)
'@vitest/coverage-v8@3.2.4(vitest@3.2.4)':
dependencies:
@@ -14415,7 +14415,7 @@ snapshots:
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.21
magic-string: 0.30.19
optionalDependencies:
vite: 7.1.11(@types/node@22.19.1)(jiti@2.6.1)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)
@@ -14432,7 +14432,7 @@ snapshots:
'@vitest/snapshot@3.2.4':
dependencies:
'@vitest/pretty-format': 3.2.4
magic-string: 0.30.21
magic-string: 0.30.19
pathe: 2.0.3
'@vitest/spy@3.2.4':
@@ -14464,18 +14464,18 @@ snapshots:
estree-walker: 2.0.2
source-map-js: 1.2.1
'@vue/compiler-core@3.5.24':
'@vue/compiler-core@3.5.23':
dependencies:
'@babel/parser': 7.28.5
'@vue/shared': 3.5.24
'@vue/shared': 3.5.23
entities: 4.5.0
estree-walker: 2.0.2
source-map-js: 1.2.1
'@vue/compiler-core@3.5.25':
'@vue/compiler-core@3.5.24':
dependencies:
'@babel/parser': 7.28.5
'@vue/shared': 3.5.25
'@vue/shared': 3.5.24
entities: 4.5.0
estree-walker: 2.0.2
source-map-js: 1.2.1
@@ -14485,16 +14485,16 @@ snapshots:
'@vue/compiler-core': 3.5.21
'@vue/shared': 3.5.21
'@vue/compiler-dom@3.5.23':
dependencies:
'@vue/compiler-core': 3.5.23
'@vue/shared': 3.5.23
'@vue/compiler-dom@3.5.24':
dependencies:
'@vue/compiler-core': 3.5.24
'@vue/shared': 3.5.24
'@vue/compiler-dom@3.5.25':
dependencies:
'@vue/compiler-core': 3.5.25
'@vue/shared': 3.5.25
'@vue/compiler-sfc@3.5.21':
dependencies:
'@babel/parser': 7.28.4
@@ -14507,6 +14507,18 @@ snapshots:
postcss: 8.5.6
source-map-js: 1.2.1
'@vue/compiler-sfc@3.5.23':
dependencies:
'@babel/parser': 7.28.5
'@vue/compiler-core': 3.5.23
'@vue/compiler-dom': 3.5.23
'@vue/compiler-ssr': 3.5.23
'@vue/shared': 3.5.23
estree-walker: 2.0.2
magic-string: 0.30.21
postcss: 8.5.6
source-map-js: 1.2.1
'@vue/compiler-sfc@3.5.24':
dependencies:
'@babel/parser': 7.28.5
@@ -14519,33 +14531,21 @@ snapshots:
postcss: 8.5.6
source-map-js: 1.2.1
'@vue/compiler-sfc@3.5.25':
dependencies:
'@babel/parser': 7.28.5
'@vue/compiler-core': 3.5.25
'@vue/compiler-dom': 3.5.25
'@vue/compiler-ssr': 3.5.25
'@vue/shared': 3.5.25
estree-walker: 2.0.2
magic-string: 0.30.21
postcss: 8.5.6
source-map-js: 1.2.1
'@vue/compiler-ssr@3.5.21':
dependencies:
'@vue/compiler-dom': 3.5.21
'@vue/shared': 3.5.21
'@vue/compiler-ssr@3.5.23':
dependencies:
'@vue/compiler-dom': 3.5.23
'@vue/shared': 3.5.23
'@vue/compiler-ssr@3.5.24':
dependencies:
'@vue/compiler-dom': 3.5.24
'@vue/shared': 3.5.24
'@vue/compiler-ssr@3.5.25':
dependencies:
'@vue/compiler-dom': 3.5.25
'@vue/shared': 3.5.25
'@vue/devtools-api@7.7.7':
dependencies:
'@vue/devtools-kit': 7.7.7
@@ -14568,19 +14568,19 @@ snapshots:
dependencies:
'@vue/shared': 3.5.21
'@vue/reactivity@3.5.25':
'@vue/reactivity@3.5.24':
dependencies:
'@vue/shared': 3.5.25
'@vue/shared': 3.5.24
'@vue/runtime-core@3.5.21':
dependencies:
'@vue/reactivity': 3.5.21
'@vue/shared': 3.5.21
'@vue/runtime-core@3.5.25':
'@vue/runtime-core@3.5.24':
dependencies:
'@vue/reactivity': 3.5.25
'@vue/shared': 3.5.25
'@vue/reactivity': 3.5.24
'@vue/shared': 3.5.24
'@vue/runtime-dom@3.5.21':
dependencies:
@@ -14589,11 +14589,11 @@ snapshots:
'@vue/shared': 3.5.21
csstype: 3.1.3
'@vue/runtime-dom@3.5.25':
'@vue/runtime-dom@3.5.24':
dependencies:
'@vue/reactivity': 3.5.25
'@vue/runtime-core': 3.5.25
'@vue/shared': 3.5.25
'@vue/reactivity': 3.5.24
'@vue/runtime-core': 3.5.24
'@vue/shared': 3.5.24
csstype: 3.1.3
'@vue/server-renderer@3.5.21(vue@3.5.21(typescript@5.7.3))':
@@ -14608,30 +14608,30 @@ snapshots:
'@vue/shared': 3.5.21
vue: 3.5.21(typescript@5.9.2)
'@vue/server-renderer@3.5.25(vue@3.5.25(typescript@5.7.3))':
'@vue/server-renderer@3.5.24(vue@3.5.24(typescript@5.7.3))':
dependencies:
'@vue/compiler-ssr': 3.5.25
'@vue/shared': 3.5.25
vue: 3.5.25(typescript@5.7.3)
'@vue/compiler-ssr': 3.5.24
'@vue/shared': 3.5.24
vue: 3.5.24(typescript@5.7.3)
'@vue/server-renderer@3.5.25(vue@3.5.25(typescript@5.9.2))':
'@vue/server-renderer@3.5.24(vue@3.5.24(typescript@5.9.2))':
dependencies:
'@vue/compiler-ssr': 3.5.25
'@vue/shared': 3.5.25
vue: 3.5.25(typescript@5.9.2)
'@vue/compiler-ssr': 3.5.24
'@vue/shared': 3.5.24
vue: 3.5.24(typescript@5.9.2)
'@vue/shared@3.5.21': {}
'@vue/shared@3.5.24': {}
'@vue/shared@3.5.23': {}
'@vue/shared@3.5.25': {}
'@vue/shared@3.5.24': {}
'@vueuse/core@12.8.2(typescript@5.7.3)':
dependencies:
'@types/web-bluetooth': 0.0.21
'@vueuse/metadata': 12.8.2
'@vueuse/shared': 12.8.2(typescript@5.7.3)
vue: 3.5.25(typescript@5.7.3)
vue: 3.5.24(typescript@5.7.3)
transitivePeerDependencies:
- typescript
@@ -14640,22 +14640,22 @@ snapshots:
'@types/web-bluetooth': 0.0.21
'@vueuse/metadata': 12.8.2
'@vueuse/shared': 12.8.2(typescript@5.9.2)
vue: 3.5.25(typescript@5.9.2)
vue: 3.5.24(typescript@5.9.2)
transitivePeerDependencies:
- typescript
'@vueuse/core@13.9.0(vue@3.5.25(typescript@5.9.2))':
'@vueuse/core@13.9.0(vue@3.5.24(typescript@5.9.2))':
dependencies:
'@types/web-bluetooth': 0.0.21
'@vueuse/metadata': 13.9.0
'@vueuse/shared': 13.9.0(vue@3.5.25(typescript@5.9.2))
vue: 3.5.25(typescript@5.9.2)
'@vueuse/shared': 13.9.0(vue@3.5.24(typescript@5.9.2))
vue: 3.5.24(typescript@5.9.2)
'@vueuse/integrations@12.8.2(axios@1.13.2)(change-case@5.4.4)(focus-trap@7.6.5)(typescript@5.7.3)':
dependencies:
'@vueuse/core': 12.8.2(typescript@5.7.3)
'@vueuse/shared': 12.8.2(typescript@5.7.3)
vue: 3.5.25(typescript@5.7.3)
vue: 3.5.24(typescript@5.7.3)
optionalDependencies:
axios: 1.13.2(debug@4.4.3)
change-case: 5.4.4
@@ -14667,7 +14667,7 @@ snapshots:
dependencies:
'@vueuse/core': 12.8.2(typescript@5.9.2)
'@vueuse/shared': 12.8.2(typescript@5.9.2)
vue: 3.5.25(typescript@5.9.2)
vue: 3.5.24(typescript@5.9.2)
optionalDependencies:
axios: 1.13.2(debug@4.4.3)
change-case: 5.4.4
@@ -14681,19 +14681,19 @@ snapshots:
'@vueuse/shared@12.8.2(typescript@5.7.3)':
dependencies:
vue: 3.5.25(typescript@5.7.3)
vue: 3.5.24(typescript@5.7.3)
transitivePeerDependencies:
- typescript
'@vueuse/shared@12.8.2(typescript@5.9.2)':
dependencies:
vue: 3.5.25(typescript@5.9.2)
vue: 3.5.24(typescript@5.9.2)
transitivePeerDependencies:
- typescript
'@vueuse/shared@13.9.0(vue@3.5.25(typescript@5.9.2))':
'@vueuse/shared@13.9.0(vue@3.5.24(typescript@5.9.2))':
dependencies:
vue: 3.5.25(typescript@5.9.2)
vue: 3.5.24(typescript@5.9.2)
'@wdio/config@7.31.1(typescript@5.7.3)':
dependencies:
@@ -16467,7 +16467,7 @@ snapshots:
detective-vue2@2.2.0(typescript@5.7.3):
dependencies:
'@dependents/detective-less': 5.0.1
'@vue/compiler-sfc': 3.5.24
'@vue/compiler-sfc': 3.5.23
detective-es6: 5.0.1
detective-sass: 6.0.1
detective-scss: 5.0.1
@@ -21583,7 +21583,7 @@ snapshots:
pathe: 2.0.3
picomatch: 4.0.3
unplugin-vue-components@28.8.0(@babel/parser@7.28.5)(vue@3.5.25(typescript@5.9.2)):
unplugin-vue-components@28.8.0(@babel/parser@7.28.5)(vue@3.5.24(typescript@5.9.2)):
dependencies:
chokidar: 3.6.0
debug: 4.4.3(supports-color@8.1.1)
@@ -21593,7 +21593,7 @@ snapshots:
tinyglobby: 0.2.15
unplugin: 2.3.10
unplugin-utils: 0.2.5
vue: 3.5.25(typescript@5.9.2)
vue: 3.5.24(typescript@5.9.2)
optionalDependencies:
'@babel/parser': 7.28.5
transitivePeerDependencies:
@@ -21983,23 +21983,23 @@ snapshots:
optionalDependencies:
typescript: 5.9.2
vue@3.5.25(typescript@5.7.3):
vue@3.5.24(typescript@5.7.3):
dependencies:
'@vue/compiler-dom': 3.5.25
'@vue/compiler-sfc': 3.5.25
'@vue/runtime-dom': 3.5.25
'@vue/server-renderer': 3.5.25(vue@3.5.25(typescript@5.7.3))
'@vue/shared': 3.5.25
'@vue/compiler-dom': 3.5.24
'@vue/compiler-sfc': 3.5.24
'@vue/runtime-dom': 3.5.24
'@vue/server-renderer': 3.5.24(vue@3.5.24(typescript@5.7.3))
'@vue/shared': 3.5.24
optionalDependencies:
typescript: 5.7.3
vue@3.5.25(typescript@5.9.2):
vue@3.5.24(typescript@5.9.2):
dependencies:
'@vue/compiler-dom': 3.5.25
'@vue/compiler-sfc': 3.5.25
'@vue/runtime-dom': 3.5.25
'@vue/server-renderer': 3.5.25(vue@3.5.25(typescript@5.9.2))
'@vue/shared': 3.5.25
'@vue/compiler-dom': 3.5.24
'@vue/compiler-sfc': 3.5.24
'@vue/runtime-dom': 3.5.24
'@vue/server-renderer': 3.5.24(vue@3.5.24(typescript@5.9.2))
'@vue/shared': 3.5.24
optionalDependencies:
typescript: 5.9.2