From fbac4c61bb64c290b98e531fdd34b4d65e95a2b6 Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Wed, 5 Feb 2025 19:27:32 -0500 Subject: [PATCH 01/50] diagram adjusts with legend width changes Co-authored-by: Pranav Mishra --- .../src/diagrams/user-journey/journeyRenderer.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index 13eb31a02..0860c4753 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -13,10 +13,12 @@ export const setConf = function (cnf) { }; const actors = {}; +let maxWidth = 0; /** @param diagram - The diagram to draw to. */ function drawActorLegend(diagram) { const conf = getConfig().journey; + maxWidth = 0; // Draw the actors let yPos = 60; Object.keys(actors).forEach((person) => { @@ -39,14 +41,19 @@ function drawActorLegend(diagram) { text: person, textMargin: conf.boxTextMargin | 5, }; - svgDraw.drawText(diagram, labelData); + const textElement = svgDraw.drawText(diagram, labelData); + const bbox = textElement.node().getBBox(); + const textLength = bbox.width; + if (textLength > maxWidth) { + maxWidth = textLength; + } yPos += 20; }); } // TODO: Cleanup? const conf = getConfig().journey; -const LEFT_MARGIN = conf.leftMargin; +let LEFT_MARGIN = 0; export const draw = function (text, id, version, diagObj) { const conf = getConfig().journey; @@ -84,6 +91,7 @@ export const draw = function (text, id, version, diagObj) { }); drawActorLegend(diagram); + LEFT_MARGIN = conf.leftMargin + maxWidth - 80; bounds.insert(0, 0, LEFT_MARGIN, Object.keys(actors).length * 50); drawTasks(diagram, tasks, 0); From 5366e8b69251493d107dda743bb330536a738929 Mon Sep 17 00:00:00 2001 From: pranavm2109 Date: Wed, 12 Feb 2025 15:19:37 -0500 Subject: [PATCH 02/50] added first draft of cypress visual tests Co-authored-by: Shahir Ahmed --- cypress/integration/rendering/journey.spec.js | 80 ++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index d8bef6d1b..8e37c8669 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -47,7 +47,7 @@ section Checkout from website const style = svg.attr('style'); expect(style).to.match(/^max-width: [\d.]+px;$/); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); - expect(maxWidthValue).to.eq(700); + //expect(maxWidthValue).to.eq(700); }); }); @@ -63,4 +63,82 @@ section Checkout from website { journey: { useMaxWidth: false } } ); }); + + it('should maintain consistent distance between widest legend label and diagram', () => { + renderGraph( + `journey + title Web hook life cycle + section Darkoob + Make preBuilt:5: Darkoob user + register slug : 5: Darkoob userf + Map slug to a Prebuilt Job:5: Darkoob user + section External Service + set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty + listen to the events : 5 : External Service + call darkoob endpoint : 5 : External Service + section Darkoob + check for inputs : 5 : DarkoobAPI + run the prebuilt job : 5 : DarkoobAPI + `, + { journey: { useMaxWidth: true } } + ); + + let rightEdgeXInitial, leftEdgeXInitial, rightEdgeXFinal, leftEdgeXFinal, initialDifference, finalDifference; + + cy.contains('tspan', 'admin Exjjjnjjjj qwerty') + .invoke('getBBox') + .then((bbox) => { + rightEdgeXInitial = bbox.x + bbox.width; + cy.log(`Right edge x-coordinate: ${rightEdgeXInitial}`); + }); + + cy.contains('div.label', 'Make preBuilt') + .invoke('getBoundingClientRect') + .then((rect) => { + leftEdgeXInitial = rect.left; + cy.log(`Left edge x-coordinate: ${leftEdgeXInitial}`); + initialDifference = leftEdgeXInitial - rightEdgeXInitial; + cy.log(`Initial Difference: ${initialDifference}`); + }); + + // renderGraph( + // `journey + // title Web hook life cycle + // section Darkoob + // Make preBuilt:5: Darkoob user + // register slug : 5: Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained + // Map slug to a Prebuilt Job:5: Darkoob user + // section External Service + // set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty + // listen to the events : 5 : External Service + // call darkoob endpoint : 5 : External Service + // section Darkoob + // check for inputs : 5 : DarkoobAPI + // run the prebuilt job : 5 : DarkoobAPI + // `, + // { journey: { useMaxWidth: true } } + // ); + + // cy.contains('tspan', 'Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained') + // .invoke('getBBox') + // .then((bbox) => { + // rightEdgeXFinal = bbox.x + bbox.width; + // cy.log(`Right edge x-coordinate final: ${rightEdgeXFinal}`); + // }); + + // cy.contains('div.label', 'Make preBuilt') + // .invoke('getBoundingClientRect') + // .then((rect) => { + // leftEdgeXFinal = rect.left; + // cy.log(`Left edge x-coordinate final: ${leftEdgeXFinal}`); + // finalDifference = leftEdgeXFinal - rightEdgeXFinal; + // cy.log(`Final Difference: ${finalDifference}`); + // }); + + // expect(initialDifference).toEqual(finalDifference); + + + }); + + }); From db4ea020ba7e9e57493b00b2236189f7fb7e36d9 Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Wed, 12 Feb 2025 18:39:03 -0500 Subject: [PATCH 03/50] testing Co-authored-by: Pranav Mishra --- cypress/integration/rendering/journey.spec.js | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index 8e37c8669..a89e613e1 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -83,50 +83,53 @@ section Checkout from website { journey: { useMaxWidth: true } } ); - let rightEdgeXInitial, leftEdgeXInitial, rightEdgeXFinal, leftEdgeXFinal, initialDifference, finalDifference; + let rightEdgeXInitial, + leftEdgeXInitial, + rightEdgeXFinal, + leftEdgeXFinal, + initialDifference, + finalDifference; - cy.contains('tspan', 'admin Exjjjnjjjj qwerty') - .invoke('getBBox') - .then((bbox) => { - rightEdgeXInitial = bbox.x + bbox.width; - cy.log(`Right edge x-coordinate: ${rightEdgeXInitial}`); - }); + cy.contains('tspan', 'admin Exjjjnjjjj qwerty').then((textBox) => { + const bbox = textBox[0].getBBox(); + const rightEdge = bbox.x + bbox.width; + console.warn(rightEdge); + }); - cy.contains('div.label', 'Make preBuilt') - .invoke('getBoundingClientRect') - .then((rect) => { - leftEdgeXInitial = rect.left; - cy.log(`Left edge x-coordinate: ${leftEdgeXInitial}`); - initialDifference = leftEdgeXInitial - rightEdgeXInitial; - cy.log(`Initial Difference: ${initialDifference}`); - }); + cy.get(':nth-child(14) > switch > foreignobject').then((rect) => { + console.warn(rect); + //const leftEdgeXInitial = rect.left; + // cy.log(`Left edge x-coordinate: ${leftEdgeXInitial}`); + // initialDifference = leftEdgeXInitial - rightEdgeXInitial; + // cy.log(`Initial Difference: ${initialDifference}`); + }); // renderGraph( // `journey // title Web hook life cycle - // section Darkoob - // Make preBuilt:5: Darkoob user + // section Darkoob + // Make preBuilt:5: Darkoob user // register slug : 5: Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained // Map slug to a Prebuilt Job:5: Darkoob user // section External Service // set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty - // listen to the events : 5 : External Service - // call darkoob endpoint : 5 : External Service - // section Darkoob + // listen to the events : 5 : External Service + // call darkoob endpoint : 5 : External Service + // section Darkoob // check for inputs : 5 : DarkoobAPI - // run the prebuilt job : 5 : DarkoobAPI + // run the prebuilt job : 5 : DarkoobAPI // `, // { journey: { useMaxWidth: true } } // ); - // cy.contains('tspan', 'Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained') + // cy.contains('tspan', 'Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained') // .invoke('getBBox') // .then((bbox) => { // rightEdgeXFinal = bbox.x + bbox.width; // cy.log(`Right edge x-coordinate final: ${rightEdgeXFinal}`); // }); - // cy.contains('div.label', 'Make preBuilt') + // cy.contains('div.label', 'Make preBuilt') // .invoke('getBoundingClientRect') // .then((rect) => { // leftEdgeXFinal = rect.left; @@ -136,9 +139,5 @@ section Checkout from website // }); // expect(initialDifference).toEqual(finalDifference); - - }); - - }); From d618b8398ee857ab848c6c2f38924b902f2cc884 Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Wed, 12 Feb 2025 19:54:56 -0500 Subject: [PATCH 04/50] adds test for journey Co-authored-by: Pranav Mishra --- cypress/integration/rendering/journey.spec.js | 97 ++++++++++--------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index a89e613e1..0cbacc594 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -64,7 +64,7 @@ section Checkout from website ); }); - it('should maintain consistent distance between widest legend label and diagram', () => { + it('should maintain sufficient space between legend labels and diagram elements', () => { renderGraph( `journey title Web hook life cycle @@ -83,61 +83,64 @@ section Checkout from website { journey: { useMaxWidth: true } } ); - let rightEdgeXInitial, - leftEdgeXInitial, - rightEdgeXFinal, - leftEdgeXFinal, - initialDifference, - finalDifference; + let LabelEndX, diagramStartX; + // Get right edge of the legend cy.contains('tspan', 'admin Exjjjnjjjj qwerty').then((textBox) => { const bbox = textBox[0].getBBox(); - const rightEdge = bbox.x + bbox.width; - console.warn(rightEdge); + LabelEndX = bbox.x + bbox.width; }); - cy.get(':nth-child(14) > switch > foreignobject').then((rect) => { - console.warn(rect); - //const leftEdgeXInitial = rect.left; - // cy.log(`Left edge x-coordinate: ${leftEdgeXInitial}`); - // initialDifference = leftEdgeXInitial - rightEdgeXInitial; - // cy.log(`Initial Difference: ${initialDifference}`); + // Get left edge of the diagram + cy.contains('foreignobject', 'Make preBuilt').then((rect) => { + diagramStartX = parseFloat(rect.attr('x')); }); - // renderGraph( - // `journey - // title Web hook life cycle - // section Darkoob - // Make preBuilt:5: Darkoob user - // register slug : 5: Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained - // Map slug to a Prebuilt Job:5: Darkoob user - // section External Service - // set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty - // listen to the events : 5 : External Service - // call darkoob endpoint : 5 : External Service - // section Darkoob - // check for inputs : 5 : DarkoobAPI - // run the prebuilt job : 5 : DarkoobAPI - // `, - // { journey: { useMaxWidth: true } } - // ); + // Assert right edge of the diagram is greater than or equal to the right edge of the label + cy.then(() => { + expect(diagramStartX).to.be.gte(LabelEndX); + }); + }); - // cy.contains('tspan', 'Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained') - // .invoke('getBBox') - // .then((bbox) => { - // rightEdgeXFinal = bbox.x + bbox.width; - // cy.log(`Right edge x-coordinate final: ${rightEdgeXFinal}`); - // }); + it('should maintain sufficient space between legend and diagram when legend labels are longer', () => { + cy.then(() => { + renderGraph( + `journey + title Web hook life cycle + section Darkoob + Make preBuilt:5: Darkoob user + register slug : 5: Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained + Map slug to a Prebuilt Job:5: Darkoob user + section External Service + set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty + listen to the events : 5 : External Service + call darkoob endpoint : 5 : External Service + section Darkoob + check for inputs : 5 : DarkoobAPI + run the prebuilt job : 5 : DarkoobAPI + `, + { journey: { useMaxWidth: true } } + ); + }); - // cy.contains('div.label', 'Make preBuilt') - // .invoke('getBoundingClientRect') - // .then((rect) => { - // leftEdgeXFinal = rect.left; - // cy.log(`Left edge x-coordinate final: ${leftEdgeXFinal}`); - // finalDifference = leftEdgeXFinal - rightEdgeXFinal; - // cy.log(`Final Difference: ${finalDifference}`); - // }); + let LabelEndX, diagramStartX; - // expect(initialDifference).toEqual(finalDifference); + // Get right edge of the legend + cy.contains('tspan', 'Darkoob userf deliberately increasing the size of this label').then( + (textBox) => { + const bbox = textBox[0].getBBox(); + LabelEndX = bbox.x + bbox.width; + } + ); + + // Get left edge of the diagram + cy.contains('foreignobject', 'Make preBuilt').then((rect) => { + diagramStartX = parseFloat(rect.attr('x')); + }); + + // Assert right edge of the diagram is greater than or equal to the right edge of the label + cy.then(() => { + expect(diagramStartX).to.be.gte(LabelEndX); + }); }); }); From 5f7c68def7eb8dc9c5e706d9d810c273dcb66584 Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Thu, 13 Feb 2025 01:46:27 -0500 Subject: [PATCH 05/50] refactor: standardize variable naming and improve legend width calculations Co-authored-by: pranavm2109 --- cypress/integration/rendering/journey.spec.js | 2 +- .../diagrams/user-journey/journeyRenderer.ts | 21 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index 0cbacc594..a30b65b84 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -47,7 +47,7 @@ section Checkout from website const style = svg.attr('style'); expect(style).to.match(/^max-width: [\d.]+px;$/); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); - //expect(maxWidthValue).to.eq(700); + expect(maxWidthValue).to.eq(700); }); }); diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index 0860c4753..a9dee0546 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -43,8 +43,7 @@ function drawActorLegend(diagram) { }; const textElement = svgDraw.drawText(diagram, labelData); - const bbox = textElement.node().getBBox(); - const textLength = bbox.width; + const textLength = textElement.node().getBBox().width; if (textLength > maxWidth) { maxWidth = textLength; } @@ -53,7 +52,7 @@ function drawActorLegend(diagram) { } // TODO: Cleanup? const conf = getConfig().journey; -let LEFT_MARGIN = 0; +let leftMargin = 0; export const draw = function (text, id, version, diagObj) { const conf = getConfig().journey; @@ -91,8 +90,8 @@ export const draw = function (text, id, version, diagObj) { }); drawActorLegend(diagram); - LEFT_MARGIN = conf.leftMargin + maxWidth - 80; - bounds.insert(0, 0, LEFT_MARGIN, Object.keys(actors).length * 50); + leftMargin = conf.leftMargin + maxWidth - 22.328125; + bounds.insert(0, 0, leftMargin, Object.keys(actors).length * 50); drawTasks(diagram, tasks, 0); const box = bounds.getBounds(); @@ -100,23 +99,23 @@ export const draw = function (text, id, version, diagObj) { diagram .append('text') .text(title) - .attr('x', LEFT_MARGIN) + .attr('x', leftMargin) .attr('font-size', '4ex') .attr('font-weight', 'bold') .attr('y', 25); } const height = box.stopy - box.starty + 2 * conf.diagramMarginY; - const width = LEFT_MARGIN + box.stopx + 2 * conf.diagramMarginX; + const width = leftMargin + box.stopx + 2 * conf.diagramMarginX; configureSvgSize(diagram, height, width, conf.useMaxWidth); // Draw activity line diagram .append('line') - .attr('x1', LEFT_MARGIN) + .attr('x1', leftMargin) .attr('y1', conf.height * 4) // One section head + one task + margins - .attr('x2', width - LEFT_MARGIN - 4) // Subtract stroke width so arrow point is retained + .attr('x2', width - leftMargin - 4) // Subtract stroke width so arrow point is retained .attr('y2', conf.height * 4) .attr('stroke-width', 4) .attr('stroke', 'black') @@ -242,7 +241,7 @@ export const drawTasks = function (diagram, tasks, verticalPos) { } const section = { - x: i * conf.taskMargin + i * conf.width + LEFT_MARGIN, + x: i * conf.taskMargin + i * conf.width + leftMargin, y: 50, text: task.section, fill, @@ -266,7 +265,7 @@ export const drawTasks = function (diagram, tasks, verticalPos) { }, {}); // Add some rendering data to the object - task.x = i * conf.taskMargin + i * conf.width + LEFT_MARGIN; + task.x = i * conf.taskMargin + i * conf.width + leftMargin; task.y = taskPos; task.width = conf.diagramMarginX; task.height = conf.diagramMarginY; From a318ea3692f19dba3aa5b20aa2fed2d57bbc75b2 Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Fri, 21 Feb 2025 16:15:24 -0500 Subject: [PATCH 06/50] removes cy.then and magic value Co-authored-by: Pranav Mishra --- cypress/integration/rendering/journey.spec.js | 10 ++++------ .../src/diagrams/user-journey/journeyRenderer.ts | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index a30b65b84..a7e280ab2 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -103,9 +103,8 @@ section Checkout from website }); it('should maintain sufficient space between legend and diagram when legend labels are longer', () => { - cy.then(() => { - renderGraph( - `journey + renderGraph( + `journey title Web hook life cycle section Darkoob Make preBuilt:5: Darkoob user @@ -119,9 +118,8 @@ section Checkout from website check for inputs : 5 : DarkoobAPI run the prebuilt job : 5 : DarkoobAPI `, - { journey: { useMaxWidth: true } } - ); - }); + { journey: { useMaxWidth: true } } + ); let LabelEndX, diagramStartX; diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index a9dee0546..06c6cdeea 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -44,7 +44,7 @@ function drawActorLegend(diagram) { const textElement = svgDraw.drawText(diagram, labelData); const textLength = textElement.node().getBBox().width; - if (textLength > maxWidth) { + if (textLength > maxWidth && textLength > conf?.leftMargin) { maxWidth = textLength; } yPos += 20; @@ -90,7 +90,7 @@ export const draw = function (text, id, version, diagObj) { }); drawActorLegend(diagram); - leftMargin = conf.leftMargin + maxWidth - 22.328125; + leftMargin = conf.leftMargin + maxWidth; bounds.insert(0, 0, leftMargin, Object.keys(actors).length * 50); drawTasks(diagram, tasks, 0); From 50816a7f98a86a4d6ebf03abd35809a09a624b9d Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Fri, 21 Feb 2025 17:35:32 -0500 Subject: [PATCH 07/50] remove magic value Co-authored-by: Pranav Mishra --- packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index 06c6cdeea..2e27cc8b5 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -44,7 +44,7 @@ function drawActorLegend(diagram) { const textElement = svgDraw.drawText(diagram, labelData); const textLength = textElement.node().getBBox().width; - if (textLength > maxWidth && textLength > conf?.leftMargin) { + if (textLength > maxWidth && textLength > conf?.leftMargin - textLength) { maxWidth = textLength; } yPos += 20; From d47e4724cbfeef8d818eaf3ad79b14bc471a4839 Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Tue, 25 Feb 2025 15:21:08 -0500 Subject: [PATCH 08/50] wraps long text into new line Co-authored-by: Pranav Mishra --- .../diagrams/user-journey/journeyRenderer.ts | 67 +++++++++++++++---- 1 file changed, 53 insertions(+), 14 deletions(-) diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index 2e27cc8b5..9158a8c82 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -19,11 +19,14 @@ let maxWidth = 0; function drawActorLegend(diagram) { const conf = getConfig().journey; maxWidth = 0; - // Draw the actors let yPos = 60; + + const getRemInPx = (rem) => { + return rem * parseFloat(getComputedStyle(document.documentElement).fontSize); + }; + Object.keys(actors).forEach((person) => { const colour = actors[person].color; - const circleData = { cx: 20, cy: yPos, @@ -34,20 +37,56 @@ function drawActorLegend(diagram) { }; svgDraw.drawCircle(diagram, circleData); - const labelData = { - x: 40, - y: yPos + 7, - fill: '#666', - text: person, - textMargin: conf.boxTextMargin | 5, - }; + // Create temporary text element to measure width + const tempText = diagram.append('text').attr('visibility', 'hidden').text(person); + const textWidth = tempText.node().getBBox().width; + tempText.remove(); - const textElement = svgDraw.drawText(diagram, labelData); - const textLength = textElement.node().getBBox().width; - if (textLength > maxWidth && textLength > conf?.leftMargin - textLength) { - maxWidth = textLength; + const maxLineLength = getRemInPx(15); + let lines = []; + + if (textWidth > maxLineLength) { + // Break the text into chunks regardless of word boundaries + let currentText = ''; + const measureText = diagram.append('text').attr('visibility', 'hidden'); + + for (const element of person) { + currentText += element; + measureText.text(currentText); + const currentWidth = measureText.node().getBBox().width; + + if (currentWidth > maxLineLength && currentText.length > 1) { + // Add hyphen only if we're breaking within a word + lines.push(currentText.slice(0, -1) + '-'); + currentText = element; + } + } + if (currentText) { + lines.push(currentText); + } + measureText.remove(); + } else { + lines = [person]; } - yPos += 20; + + // Draw the text lines + lines.forEach((line, index) => { + const labelData = { + x: 40, + y: yPos + 7 + index * 20, + fill: '#666', + text: line, + textMargin: conf.boxTextMargin | 5, + }; + const textElement = svgDraw.drawText(diagram, labelData); + const lineWidth = textElement.node().getBBox().width; + + if (lineWidth > maxWidth && lineWidth > conf?.leftMargin - lineWidth) { + maxWidth = lineWidth; + } + }); + + yPos += Math.max(20, lines.length * 20); }); } // TODO: Cleanup? From ad6248147c1823f7eeba2ecaf92c25bf2abc7419 Mon Sep 17 00:00:00 2001 From: pranavm2109 Date: Tue, 25 Feb 2025 15:29:29 -0500 Subject: [PATCH 09/50] revised current cypress test Co-authored-by: Shahir Ahmed --- cypress/integration/rendering/journey.spec.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index a7e280ab2..41af44ae6 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -124,12 +124,10 @@ section Checkout from website let LabelEndX, diagramStartX; // Get right edge of the legend - cy.contains('tspan', 'Darkoob userf deliberately increasing the size of this label').then( - (textBox) => { - const bbox = textBox[0].getBBox(); - LabelEndX = bbox.x + bbox.width; - } - ); + cy.contains('tspan', 'Darkoob userf').then((textBox) => { + const bbox = textBox[0].getBBox(); + LabelEndX = bbox.x + bbox.width; + }); // Get left edge of the diagram cy.contains('foreignobject', 'Make preBuilt').then((rect) => { From edbf125c83f09c57a6039e08ecb0acf91b4db59a Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Tue, 25 Feb 2025 15:43:00 -0500 Subject: [PATCH 10/50] wraps long text into new line Co-authored-by: Pranav Mishra --- .../mermaid/src/diagrams/user-journey/journeyRenderer.ts | 2 +- packages/mermaid/src/schemas/config.schema.yaml | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index 9158a8c82..d0bb8e0c1 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -41,7 +41,7 @@ function drawActorLegend(diagram) { const tempText = diagram.append('text').attr('visibility', 'hidden').text(person); const textWidth = tempText.node().getBBox().width; tempText.remove(); - + let configObject = getConfig().journey; const maxLineLength = getRemInPx(15); let lines = []; diff --git a/packages/mermaid/src/schemas/config.schema.yaml b/packages/mermaid/src/schemas/config.schema.yaml index e1014e889..e94c3d69c 100644 --- a/packages/mermaid/src/schemas/config.schema.yaml +++ b/packages/mermaid/src/schemas/config.schema.yaml @@ -1485,6 +1485,12 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) type: integer default: 150 minimum: 0 + maxLabelWidth: + description: Maximum width of actor labels + type: integer + default: 360 + minimum: 240 + maximum: 480 width: description: Width of actor boxes type: integer From 5510f18d333725b17bd94b461c5ee0dc46d84d63 Mon Sep 17 00:00:00 2001 From: pranavm2109 Date: Tue, 25 Feb 2025 15:50:10 -0500 Subject: [PATCH 11/50] removed function to get rem in px since config schema now has maxLabelWidth Co-authored-by: Shahir Ahmed --- .../mermaid/src/diagrams/user-journey/journeyRenderer.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index d0bb8e0c1..8e221f6b4 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -21,10 +21,6 @@ function drawActorLegend(diagram) { maxWidth = 0; let yPos = 60; - const getRemInPx = (rem) => { - return rem * parseFloat(getComputedStyle(document.documentElement).fontSize); - }; - Object.keys(actors).forEach((person) => { const colour = actors[person].color; const circleData = { @@ -41,8 +37,8 @@ function drawActorLegend(diagram) { const tempText = diagram.append('text').attr('visibility', 'hidden').text(person); const textWidth = tempText.node().getBBox().width; tempText.remove(); - let configObject = getConfig().journey; - const maxLineLength = getRemInPx(15); + const journeyConfigObject = getConfig().journey; + const maxLineLength = journeyConfigObject.maxLabelWidth; let lines = []; if (textWidth > maxLineLength) { From 3724d112554c645faee6b4576dfbef0d78a546e2 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 25 Feb 2025 20:55:26 +0000 Subject: [PATCH 12/50] [autofix.ci] apply automated fixes --- packages/mermaid/src/config.type.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 86281cd52..ff547eeec 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -546,6 +546,10 @@ export interface JourneyDiagramConfig extends BaseDiagramConfig { * Margin between actors */ leftMargin?: number; + /** + * Maximum width of actor labels + */ + maxLabelWidth?: number; /** * Width of actor boxes */ From aaf15fccc14c0282fd61b35fb13eb69d8936d89e Mon Sep 17 00:00:00 2001 From: pranavm2109 Date: Tue, 25 Feb 2025 16:13:14 -0500 Subject: [PATCH 13/50] added first draft of test to see if label text is being wrapped in different lines Co-authored-by: Shahir Ahmed --- cypress/integration/rendering/journey.spec.js | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index 41af44ae6..0cd1945c7 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -139,4 +139,39 @@ section Checkout from website expect(diagramStartX).to.be.gte(LabelEndX); }); }); + + it('should check the width and number of lines of the Darkoob user text element', () => { + renderGraph( + `journey + title Web hook life cycle + section Darkoob + Make preBuilt:5: Darkoob user + register slug : 5: Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained + Map slug to a Prebuilt Job:5: Darkoob user + section External Service + set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty + listen to the events : 5 : External Service + call darkoob endpoint : 5 : External Service + section Darkoob + check for inputs : 5 : DarkoobAPI + run the prebuilt job : 5 : DarkoobAPI + `, + { journey: { useMaxWidth: true } } + ); + + cy.contains('tspan', 'Darkoob user').then((textBox) => { + const bbox = textBox[0].getBBox(); + const textWidth = bbox.width; + + expect(textWidth).to.equal(320); + }); + + cy.contains('tspan', 'Darkoob user') + .parent() + .then((textElement) => { + const numLines = textElement.find('tspan').length; + + expect(numLines).to.equal(3); + }); + }); }); From 7c7fd4bc5efc2738a1647d93377870ab2fbe006b Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Tue, 25 Feb 2025 18:40:27 -0500 Subject: [PATCH 14/50] adds test for line wrapping Co-authored-by: Pranav Mishra --- cypress/integration/rendering/journey.spec.js | 153 +++++++++++------- .../diagrams/user-journey/journeyRenderer.ts | 15 +- 2 files changed, 103 insertions(+), 65 deletions(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index 0cd1945c7..ec7788439 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -64,44 +64,6 @@ section Checkout from website ); }); - it('should maintain sufficient space between legend labels and diagram elements', () => { - renderGraph( - `journey - title Web hook life cycle - section Darkoob - Make preBuilt:5: Darkoob user - register slug : 5: Darkoob userf - Map slug to a Prebuilt Job:5: Darkoob user - section External Service - set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty - listen to the events : 5 : External Service - call darkoob endpoint : 5 : External Service - section Darkoob - check for inputs : 5 : DarkoobAPI - run the prebuilt job : 5 : DarkoobAPI - `, - { journey: { useMaxWidth: true } } - ); - - let LabelEndX, diagramStartX; - - // Get right edge of the legend - cy.contains('tspan', 'admin Exjjjnjjjj qwerty').then((textBox) => { - const bbox = textBox[0].getBBox(); - LabelEndX = bbox.x + bbox.width; - }); - - // Get left edge of the diagram - cy.contains('foreignobject', 'Make preBuilt').then((rect) => { - diagramStartX = parseFloat(rect.attr('x')); - }); - - // Assert right edge of the diagram is greater than or equal to the right edge of the label - cy.then(() => { - expect(diagramStartX).to.be.gte(LabelEndX); - }); - }); - it('should maintain sufficient space between legend and diagram when legend labels are longer', () => { renderGraph( `journey @@ -140,38 +102,105 @@ section Checkout from website }); }); - it('should check the width and number of lines of the Darkoob user text element', () => { + it('should wrap a single long word with hyphenation', () => { renderGraph( - `journey - title Web hook life cycle - section Darkoob - Make preBuilt:5: Darkoob user - register slug : 5: Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained - Map slug to a Prebuilt Job:5: Darkoob user - section External Service - set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty - listen to the events : 5 : External Service - call darkoob endpoint : 5 : External Service - section Darkoob - check for inputs : 5 : DarkoobAPI - run the prebuilt job : 5 : DarkoobAPI + ` + --- + config: + journey: + maxLabelWidth: 100 + --- + journey + title Long Word Test + section Test + VeryLongWord: 5: Supercalifragilisticexpialidocious `, { journey: { useMaxWidth: true } } ); - cy.contains('tspan', 'Darkoob user').then((textBox) => { - const bbox = textBox[0].getBBox(); - const textWidth = bbox.width; - - expect(textWidth).to.equal(320); + // Check that at least one line ends with a hyphen, indicating a mid-word break. + cy.get('tspan').then((tspans) => { + const hasHyphen = [...tspans].some((t) => t.textContent.trim().endsWith('-')); + return expect(hasHyphen).to.be.true; }); + }); - cy.contains('tspan', 'Darkoob user') - .parent() - .then((textElement) => { - const numLines = textElement.find('tspan').length; + it('should wrap text on whitespace without adding hyphens', () => { + renderGraph( + ` + --- + config: + journey: + maxLabelWidth: 200 + --- + journey + title Whitespace Test + section Test + TextWithSpaces: 5: Gustavo Fring is played by Giancarlo Esposito. + `, + { journey: { useMaxWidth: true } } + ); - expect(numLines).to.equal(3); + // Verify that none of the text spans end with a hyphen. + cy.get('tspan').each(($el) => { + const text = $el.text(); + expect(text.trim()).not.to.match(/-$/); + }); + }); + + it('should wrap long labels into multiple lines, keep them under max width, and maintain margins', () => { + renderGraph( + ` + --- + config: + journey: + maxLabelWidth: 320 + --- + journey + title User Journey Example + section Onboarding + Sign Up: 5: Sam Sam Sam Sam Sam Sam Sam Sam Sam Sam Sam Sam ... + section Engagement + Browse Features: 3 + Use Core Functionality: 4 + `, + { journey: { useMaxWidth: true } } + ); + + let diagramStartX; + + // Get the diagram's left edge + cy.contains('foreignobject', 'Sign Up') + .then(($diagram) => { + diagramStartX = parseFloat($diagram.attr('x')); + }) + .then(() => { + // Get all legend lines that include "Sam" + cy.get('text.legend') + .filter((i, el) => el.textContent.includes('Sam')) + .then(($lines) => { + // Check that there are two lines + expect($lines.length).to.be.equal(2); + + // Check that for all but the last line it nearly fills the max width + $lines.each((index, el) => { + const bbox = el.getBBox(); + if (index < $lines.length - 1) { + expect(bbox.width).to.be.closeTo(320, 5); + } else { + // Last line may be shorter + expect(bbox.width).to.be.lte(320); + } + }); + + // check margin between diagram and legend is maintained + const longestBBox = $lines.get(0).getBBox(); // longest Line's bbox + if (diagramStartX && longestBBox) { + const legendRightEdge = longestBBox.x + longestBBox.width; + const margin = diagramStartX - legendRightEdge; + expect(margin).to.be.closeTo(100, 2); // expect margin to be around 100 + } + }); }); }); }); diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index 8e221f6b4..821f023a0 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -52,9 +52,18 @@ function drawActorLegend(diagram) { const currentWidth = measureText.node().getBBox().width; if (currentWidth > maxLineLength && currentText.length > 1) { - // Add hyphen only if we're breaking within a word - lines.push(currentText.slice(0, -1) + '-'); - currentText = element; + let lineToPush = currentText.slice(0, -1); + + // If the line ends with a space, trim it and do not add a hyphen. + if (lineToPush.endsWith(' ')) { + lineToPush = lineToPush.trimEnd(); + } else { + lineToPush = lineToPush + '-'; + } + lines.push(lineToPush); + + // If the breaking character is a space, start fresh; otherwise, start with the character. + currentText = element === ' ' ? '' : element; } } if (currentText) { From 55e1dd0eadeac1b55020d4af85aae6c6b3461b8c Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Tue, 18 Mar 2025 15:32:04 -0400 Subject: [PATCH 15/50] implemented knuth-plass line-breaking algorithm Co-authored-by: pranavm2109 --- .../diagrams/user-journey/journeyRenderer.ts | 85 +++++++++---------- 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index 821f023a0..aecbe9d2e 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -18,7 +18,7 @@ let maxWidth = 0; /** @param diagram - The diagram to draw to. */ function drawActorLegend(diagram) { const conf = getConfig().journey; - maxWidth = 0; + maxWidth = conf.maxLabelWidth; // Ensures we don't exceed this width let yPos = 60; Object.keys(actors).forEach((person) => { @@ -33,67 +33,62 @@ function drawActorLegend(diagram) { }; svgDraw.drawCircle(diagram, circleData); - // Create temporary text element to measure width - const tempText = diagram.append('text').attr('visibility', 'hidden').text(person); - const textWidth = tempText.node().getBBox().width; - tempText.remove(); - const journeyConfigObject = getConfig().journey; - const maxLineLength = journeyConfigObject.maxLabelWidth; - let lines = []; + const words = person.split(' '); // Split text into words + const lines = []; + let currentLine = ''; - if (textWidth > maxLineLength) { - // Break the text into chunks regardless of word boundaries - let currentText = ''; - const measureText = diagram.append('text').attr('visibility', 'hidden'); + const measureText = diagram.append('text').attr('visibility', 'hidden'); - for (const element of person) { - currentText += element; - measureText.text(currentText); - const currentWidth = measureText.node().getBBox().width; + words.forEach((word, _index) => { + const testLine = currentLine ? `${currentLine} ${word}` : word; + measureText.text(testLine); + const textWidth = measureText.node().getBBox().width; - if (currentWidth > maxLineLength && currentText.length > 1) { - let lineToPush = currentText.slice(0, -1); - - // If the line ends with a space, trim it and do not add a hyphen. - if (lineToPush.endsWith(' ')) { - lineToPush = lineToPush.trimEnd(); - } else { - lineToPush = lineToPush + '-'; - } - lines.push(lineToPush); - - // If the breaking character is a space, start fresh; otherwise, start with the character. - currentText = element === ' ' ? '' : element; + if (textWidth > maxWidth) { + if (currentLine) { + lines.push(currentLine); // Push previous line before adding a new word } - } - if (currentText) { - lines.push(currentText); - } - measureText.remove(); - } else { - lines = [person]; - } + currentLine = word; - // Draw the text lines + // If a single word is too long, break it + if (measureText.node().getBBox().width > maxWidth) { + let brokenWord = ''; + for (const char of word) { + brokenWord += char; + measureText.text(brokenWord + '-'); + if (measureText.node().getBBox().width > maxWidth) { + lines.push(brokenWord.slice(0, -1) + '-'); // Break word with a hyphen + brokenWord = char; + } + } + currentLine = brokenWord; + } + } else { + currentLine = testLine; + } + }); + + if (currentLine) { + lines.push(currentLine); + } + measureText.remove(); + + // Draw the text lines within the fixed width lines.forEach((line, index) => { const labelData = { x: 40, y: yPos + 7 + index * 20, fill: '#666', text: line, - textMargin: conf.boxTextMargin | 5, + textMargin: conf.boxTextMargin || 5, }; - const textElement = svgDraw.drawText(diagram, labelData); - const lineWidth = textElement.node().getBBox().width; - - if (lineWidth > maxWidth && lineWidth > conf?.leftMargin - lineWidth) { - maxWidth = lineWidth; - } + svgDraw.drawText(diagram, labelData); }); yPos += Math.max(20, lines.length * 20); }); } + // TODO: Cleanup? const conf = getConfig().journey; let leftMargin = 0; From b2ab34ca2bb0062c6fbf5e60c1e66446e2111d9a Mon Sep 17 00:00:00 2001 From: pranavm2109 Date: Tue, 18 Mar 2025 15:36:50 -0400 Subject: [PATCH 16/50] fixed linting issue Co-authored-by: Shahir Ahmed --- packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index aecbe9d2e..28d750e1c 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -80,7 +80,7 @@ function drawActorLegend(diagram) { y: yPos + 7 + index * 20, fill: '#666', text: line, - textMargin: conf.boxTextMargin || 5, + textMargin: conf.boxTextMargin ?? 5, }; svgDraw.drawText(diagram, labelData); }); From 20927a1c8ed1a6b7c33d5e72c988b990552acd01 Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Tue, 18 Mar 2025 15:39:58 -0400 Subject: [PATCH 17/50] remove max and min attributes for maxLabelWidth Co-authored-by: pranavm2109 --- packages/mermaid/src/schemas/config.schema.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/mermaid/src/schemas/config.schema.yaml b/packages/mermaid/src/schemas/config.schema.yaml index 5c9eb5a89..ce2cc8a34 100644 --- a/packages/mermaid/src/schemas/config.schema.yaml +++ b/packages/mermaid/src/schemas/config.schema.yaml @@ -1497,8 +1497,6 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) description: Maximum width of actor labels type: integer default: 360 - minimum: 240 - maximum: 480 width: description: Width of actor boxes type: integer From cfbd05515edc6074dfcad4d2312fda63f4900c27 Mon Sep 17 00:00:00 2001 From: Regis Bittencourt Date: Tue, 18 Mar 2025 20:53:19 -0300 Subject: [PATCH 18/50] Remove duplicates in integrations-community.md --- packages/mermaid/src/docs/ecosystem/integrations-community.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/mermaid/src/docs/ecosystem/integrations-community.md b/packages/mermaid/src/docs/ecosystem/integrations-community.md index 84040a3cd..28e13df0a 100644 --- a/packages/mermaid/src/docs/ecosystem/integrations-community.md +++ b/packages/mermaid/src/docs/ecosystem/integrations-community.md @@ -262,7 +262,6 @@ Communication tools and platforms - [reveal.js-mermaid-plugin](https://github.com/ludwick/reveal.js-mermaid-plugin) - [Reveal CK](https://github.com/jedcn/reveal-ck) - [reveal-ck-mermaid-plugin](https://github.com/tmtm/reveal-ck-mermaid-plugin) -- [mermaid-isomorphic](https://github.com/remcohaszing/mermaid-isomorphic) -- [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server) + From f28f7b713dc1f797c39375e3da5f58a693639fbc Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 18 Mar 2025 23:58:40 +0000 Subject: [PATCH 19/50] [autofix.ci] apply automated fixes --- docs/ecosystem/integrations-community.md | 2 -- packages/mermaid/src/docs/ecosystem/integrations-community.md | 1 - 2 files changed, 3 deletions(-) diff --git a/docs/ecosystem/integrations-community.md b/docs/ecosystem/integrations-community.md index 1dbfab8b3..dc5349a9f 100644 --- a/docs/ecosystem/integrations-community.md +++ b/docs/ecosystem/integrations-community.md @@ -267,7 +267,5 @@ Communication tools and platforms - [reveal.js-mermaid-plugin](https://github.com/ludwick/reveal.js-mermaid-plugin) - [Reveal CK](https://github.com/jedcn/reveal-ck) - [reveal-ck-mermaid-plugin](https://github.com/tmtm/reveal-ck-mermaid-plugin) -- [mermaid-isomorphic](https://github.com/remcohaszing/mermaid-isomorphic) -- [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server) diff --git a/packages/mermaid/src/docs/ecosystem/integrations-community.md b/packages/mermaid/src/docs/ecosystem/integrations-community.md index 28e13df0a..83b0ffb3d 100644 --- a/packages/mermaid/src/docs/ecosystem/integrations-community.md +++ b/packages/mermaid/src/docs/ecosystem/integrations-community.md @@ -263,5 +263,4 @@ Communication tools and platforms - [Reveal CK](https://github.com/jedcn/reveal-ck) - [reveal-ck-mermaid-plugin](https://github.com/tmtm/reveal-ck-mermaid-plugin) - From 044a3d968673c8ff616f8b838cc35fe76bfb28b4 Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Wed, 19 Mar 2025 20:34:44 -0400 Subject: [PATCH 20/50] Set legend width baseline (conf.leftMargin) and expand dynamically Co-authored-by: pranavm2109 --- cypress/integration/rendering/journey.spec.js | 10 +- .../diagrams/user-journey/journeyRenderer.ts | 108 +++++++++++------- 2 files changed, 73 insertions(+), 45 deletions(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index ec7788439..2e0b0dc40 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -136,7 +136,7 @@ section Checkout from website journey title Whitespace Test section Test - TextWithSpaces: 5: Gustavo Fring is played by Giancarlo Esposito. + TextWithSpaces: 5: Gustavo Fring is played by Giancarlo Esposito and is a character in Breaking Bad. `, { journey: { useMaxWidth: true } } ); @@ -159,7 +159,9 @@ section Checkout from website journey title User Journey Example section Onboarding - Sign Up: 5: Sam Sam Sam Sam Sam Sam Sam Sam Sam Sam Sam Sam ... + Sign Up: 5: This is a long label that will be split into multiple lines to test the wrapping functionality + Browse Features: 3: This is another long label that will be split into multiple lines to test the wrapping functionality + Use Core Functionality: 4: This is yet another long label that will be split into multiple lines to test the wrapping functionality section Engagement Browse Features: 3 Use Core Functionality: 4 @@ -177,10 +179,10 @@ section Checkout from website .then(() => { // Get all legend lines that include "Sam" cy.get('text.legend') - .filter((i, el) => el.textContent.includes('Sam')) + .filter((i, el) => el.textContent.includes('long')) .then(($lines) => { // Check that there are two lines - expect($lines.length).to.be.equal(2); + expect($lines.length).to.be.equal(9); // Check that for all but the last line it nearly fills the max width $lines.each((index, el) => { diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index 28d750e1c..bb3386bfc 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -18,7 +18,8 @@ let maxWidth = 0; /** @param diagram - The diagram to draw to. */ function drawActorLegend(diagram) { const conf = getConfig().journey; - maxWidth = conf.maxLabelWidth; // Ensures we don't exceed this width + const maxLabelWidth = conf.maxLabelWidth; + maxWidth = 0; let yPos = 60; Object.keys(actors).forEach((person) => { @@ -33,47 +34,63 @@ function drawActorLegend(diagram) { }; svgDraw.drawCircle(diagram, circleData); - const words = person.split(' '); // Split text into words - const lines = []; - let currentLine = ''; - - const measureText = diagram.append('text').attr('visibility', 'hidden'); - - words.forEach((word, _index) => { - const testLine = currentLine ? `${currentLine} ${word}` : word; - measureText.text(testLine); - const textWidth = measureText.node().getBBox().width; - - if (textWidth > maxWidth) { - if (currentLine) { - lines.push(currentLine); // Push previous line before adding a new word - } - currentLine = word; - - // If a single word is too long, break it - if (measureText.node().getBBox().width > maxWidth) { - let brokenWord = ''; - for (const char of word) { - brokenWord += char; - measureText.text(brokenWord + '-'); - if (measureText.node().getBBox().width > maxWidth) { - lines.push(brokenWord.slice(0, -1) + '-'); // Break word with a hyphen - brokenWord = char; - } - } - currentLine = brokenWord; - } - } else { - currentLine = testLine; - } - }); - - if (currentLine) { - lines.push(currentLine); - } + // First, measure the full text width without wrapping. + let measureText = diagram.append('text').attr('visibility', 'hidden').text(person); + const fullTextWidth = measureText.node().getBBox().width; measureText.remove(); - // Draw the text lines within the fixed width + let lines = []; + + // If the text is naturally within the max width, use it as a single line. + if (fullTextWidth <= maxLabelWidth) { + lines = [person]; + } else { + // Otherwise, wrap the text using the knuth-plass algorithm. + const words = person.split(' '); // Split the text into words. + let currentLine = ''; + measureText = diagram.append('text').attr('visibility', 'hidden'); + + words.forEach((word) => { + // check the width of the line with the new word. + const testLine = currentLine ? `${currentLine} ${word}` : word; + measureText.text(testLine); + const textWidth = measureText.node().getBBox().width; + + if (textWidth > maxLabelWidth) { + // If adding the new word exceeds max width, push the current line. + if (currentLine) { + lines.push(currentLine); + } + currentLine = word; // Start a new line with the current word. + + // If the word itself is too long, break it with a hyphen. + measureText.text(word); + if (measureText.node().getBBox().width > maxLabelWidth) { + let brokenWord = ''; + for (const char of word) { + brokenWord += char; + measureText.text(brokenWord + '-'); + if (measureText.node().getBBox().width > maxLabelWidth) { + // Push the broken part with a hyphen. + lines.push(brokenWord.slice(0, -1) + '-'); + brokenWord = char; + } + } + currentLine = brokenWord; + } + } else { + // If the line with the new word fits, add the new word to the current line. + currentLine = testLine; + } + }); + + // Push the last line. + if (currentLine) { + lines.push(currentLine); + } + measureText.remove(); // Remove the text element used for measuring. + } + lines.forEach((line, index) => { const labelData = { x: 40, @@ -82,7 +99,16 @@ function drawActorLegend(diagram) { text: line, textMargin: conf.boxTextMargin ?? 5, }; - svgDraw.drawText(diagram, labelData); + + // Draw the text and measure the width. + const textElement = svgDraw.drawText(diagram, labelData); + const lineWidth = textElement.node().getBBox().width; + + // Use conf.leftMargin as the initial spacing baseline, + // but expand maxWidth if the line is wider. + if (lineWidth > maxWidth && lineWidth > conf.leftMargin - lineWidth) { + maxWidth = lineWidth; + } }); yPos += Math.max(20, lines.length * 20); From ea3925455686083b5ee2b0bd1d3043e64632a5de Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Wed, 19 Mar 2025 20:41:43 -0400 Subject: [PATCH 21/50] ensure maxLabelWidth is a number Co-authored-by: pranavm2109 --- packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index bb3386bfc..75a441d31 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -22,6 +22,10 @@ function drawActorLegend(diagram) { maxWidth = 0; let yPos = 60; + if (isNaN(maxLabelWidth)) { + throw new Error('maxLabelWidth must be a number'); + } + Object.keys(actors).forEach((person) => { const colour = actors[person].color; const circleData = { From 573b6d9ba7fee75811d2af7e420c357b1e58147f Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Wed, 19 Mar 2025 20:58:17 -0400 Subject: [PATCH 22/50] remove redundant test Co-authored-by: pranavm2109 --- packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index 75a441d31..bb3386bfc 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -22,10 +22,6 @@ function drawActorLegend(diagram) { maxWidth = 0; let yPos = 60; - if (isNaN(maxLabelWidth)) { - throw new Error('maxLabelWidth must be a number'); - } - Object.keys(actors).forEach((person) => { const colour = actors[person].color; const circleData = { From b322392f971ce2c7b4ed0ccc351362244c74554d Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Wed, 19 Mar 2025 21:18:45 -0400 Subject: [PATCH 23/50] refactor tests Co-authored-by: pranavm2109 --- cypress/integration/rendering/journey.spec.js | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index 2e0b0dc40..4c4d60f65 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -177,32 +177,24 @@ section Checkout from website diagramStartX = parseFloat($diagram.attr('x')); }) .then(() => { - // Get all legend lines that include "Sam" - cy.get('text.legend') - .filter((i, el) => el.textContent.includes('long')) - .then(($lines) => { - // Check that there are two lines - expect($lines.length).to.be.equal(9); + cy.get('text.legend').then(($lines) => { + // Check that there are two lines + expect($lines.length).to.be.equal(9); - // Check that for all but the last line it nearly fills the max width - $lines.each((index, el) => { - const bbox = el.getBBox(); - if (index < $lines.length - 1) { - expect(bbox.width).to.be.closeTo(320, 5); - } else { - // Last line may be shorter - expect(bbox.width).to.be.lte(320); - } - }); - - // check margin between diagram and legend is maintained - const longestBBox = $lines.get(0).getBBox(); // longest Line's bbox - if (diagramStartX && longestBBox) { - const legendRightEdge = longestBBox.x + longestBBox.width; - const margin = diagramStartX - legendRightEdge; - expect(margin).to.be.closeTo(100, 2); // expect margin to be around 100 - } + // Check that all lines are under the max width + $lines.each((index, el) => { + const bbox = el.getBBox(); + expect(bbox.width).to.be.lte(320); }); + + // check baseline margin between diagram and legend is maintained + const longestBBox = $lines.get(7).getBBox(); // longest Line's bbox + if (diagramStartX && longestBBox) { + const legendRightEdge = longestBBox.x + longestBBox.width; + const margin = diagramStartX - legendRightEdge; + expect(margin).to.be.closeTo(150, 2); + } + }); }); }); }); From 2d583b186d357a5605a9030ed660ebdc97e481df Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Wed, 19 Mar 2025 22:51:02 -0400 Subject: [PATCH 24/50] fix some pixel issues Co-authored-by: pranavm2109 --- cypress/integration/rendering/journey.spec.js | 13 ++++--------- .../src/diagrams/user-journey/journeyRenderer.ts | 10 +++++----- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index 4c4d60f65..b03e48a38 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -169,7 +169,7 @@ section Checkout from website { journey: { useMaxWidth: true } } ); - let diagramStartX; + let diagramStartX, maxLineWidth; // Get the diagram's left edge cy.contains('foreignobject', 'Sign Up') @@ -178,22 +178,17 @@ section Checkout from website }) .then(() => { cy.get('text.legend').then(($lines) => { - // Check that there are two lines + // Check that there are multiple lines expect($lines.length).to.be.equal(9); // Check that all lines are under the max width $lines.each((index, el) => { const bbox = el.getBBox(); expect(bbox.width).to.be.lte(320); + maxLineWidth = Math.max(maxLineWidth || 0, bbox.width); }); - // check baseline margin between diagram and legend is maintained - const longestBBox = $lines.get(7).getBBox(); // longest Line's bbox - if (diagramStartX && longestBBox) { - const legendRightEdge = longestBBox.x + longestBBox.width; - const margin = diagramStartX - legendRightEdge; - expect(margin).to.be.closeTo(150, 2); - } + expect(diagramStartX - 150).to.be.closeTo(maxLineWidth, 2); }); }); }); diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index bb3386bfc..64e21a10e 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -36,7 +36,7 @@ function drawActorLegend(diagram) { // First, measure the full text width without wrapping. let measureText = diagram.append('text').attr('visibility', 'hidden').text(person); - const fullTextWidth = measureText.node().getBBox().width; + const fullTextWidth = measureText.node().getBoundingClientRect().width; measureText.remove(); let lines = []; @@ -54,7 +54,7 @@ function drawActorLegend(diagram) { // check the width of the line with the new word. const testLine = currentLine ? `${currentLine} ${word}` : word; measureText.text(testLine); - const textWidth = measureText.node().getBBox().width; + const textWidth = measureText.node().getBoundingClientRect().width; if (textWidth > maxLabelWidth) { // If adding the new word exceeds max width, push the current line. @@ -65,12 +65,12 @@ function drawActorLegend(diagram) { // If the word itself is too long, break it with a hyphen. measureText.text(word); - if (measureText.node().getBBox().width > maxLabelWidth) { + if (measureText.node().getBoundingClientRect().width > maxLabelWidth) { let brokenWord = ''; for (const char of word) { brokenWord += char; measureText.text(brokenWord + '-'); - if (measureText.node().getBBox().width > maxLabelWidth) { + if (measureText.node().getBoundingClientRect().width > maxLabelWidth) { // Push the broken part with a hyphen. lines.push(brokenWord.slice(0, -1) + '-'); brokenWord = char; @@ -102,7 +102,7 @@ function drawActorLegend(diagram) { // Draw the text and measure the width. const textElement = svgDraw.drawText(diagram, labelData); - const lineWidth = textElement.node().getBBox().width; + const lineWidth = textElement.node().getBoundingClientRect().width; // Use conf.leftMargin as the initial spacing baseline, // but expand maxWidth if the line is wider. From f7e31a978b137f807a1a08c88360bcd081256f10 Mon Sep 17 00:00:00 2001 From: Shahir Ahmed Date: Wed, 19 Mar 2025 23:44:21 -0400 Subject: [PATCH 25/50] update docs Co-authored-by: pranavm2109 --- cypress/integration/rendering/journey.spec.js | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index b03e48a38..2d6c14c9d 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -64,6 +64,35 @@ section Checkout from website ); }); + it('should initialize with a left margin of 150px for user journeys', () => { + renderGraph( + ` + --- + config: + journey: + maxLabelWidth: 320 + --- + journey + title User Journey Example + section Onboarding + Sign Up: 5: + Browse Features: 3: + Use Core Functionality: 4: + section Engagement + Browse Features: 3 + Use Core Functionality: 4 + `, + { journey: { useMaxWidth: true } } + ); + + let diagramStartX; + + cy.contains('foreignobject', 'Sign Up').then(($diagram) => { + diagramStartX = parseFloat($diagram.attr('x')); + expect(diagramStartX).to.be.closeTo(150, 2); + }); + }); + it('should maintain sufficient space between legend and diagram when legend labels are longer', () => { renderGraph( `journey @@ -118,7 +147,7 @@ section Checkout from website { journey: { useMaxWidth: true } } ); - // Check that at least one line ends with a hyphen, indicating a mid-word break. + // Verify that the line ends with a hyphen, indicating proper hyphenation for words exceeding maxLabelWidth. cy.get('tspan').then((tspans) => { const hasHyphen = [...tspans].some((t) => t.textContent.trim().endsWith('-')); return expect(hasHyphen).to.be.true; @@ -171,7 +200,7 @@ section Checkout from website let diagramStartX, maxLineWidth; - // Get the diagram's left edge + // Get the diagram's left edge x-coordinate cy.contains('foreignobject', 'Sign Up') .then(($diagram) => { diagramStartX = parseFloat($diagram.attr('x')); @@ -181,14 +210,17 @@ section Checkout from website // Check that there are multiple lines expect($lines.length).to.be.equal(9); - // Check that all lines are under the max width + // Check that all lines are under the maxLabelWidth $lines.each((index, el) => { const bbox = el.getBBox(); expect(bbox.width).to.be.lte(320); maxLineWidth = Math.max(maxLineWidth || 0, bbox.width); }); - expect(diagramStartX - 150).to.be.closeTo(maxLineWidth, 2); + /** The expected margin between the diagram and the legend is 150px, as defined by + * conf.leftMargin in user-journey-config.js + */ + expect(diagramStartX - maxLineWidth).to.be.closeTo(150, 2); }); }); }); From 0104d19f6602800d18f3759bb0d0164bf4d750be Mon Sep 17 00:00:00 2001 From: isaiah robinson <95643215+internetisaiah@users.noreply.github.com> Date: Thu, 27 Mar 2025 15:47:43 -0700 Subject: [PATCH 26/50] Fix formatting of ELK example in ERD + clarify usage --- .../docs/syntax/entityRelationshipDiagram.md | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md b/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md index 46fb7ee86..cb0db0844 100644 --- a/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md +++ b/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md @@ -409,17 +409,33 @@ erDiagram ### Renderer -The layout of the diagram is done with the renderer. The default renderer is dagre. +The layout of the diagram is handled by [`render()`](../config/setup/mermaid/interfaces/Mermaid.md#render). The default layout is dagre. -You can opt to use an alternate renderer named elk by editing the configuration. The elk renderer is better for larger and/or more complex diagrams. +For larger or more-complex diagrams, you can alternatively apply the ELK (Eclipse Layout Kernel) layout using your YAML frontmatter's `config`. For more information, see [Customizing ELK Layout](../intro/syntax-reference.md). ``` --- - config: - layout: elk +config: + layout: elk --- ``` +Your Mermaid code should be similar to the following: + +``````mermaid-example +```mermaid +--- +title: Order example +config: + layout: elk +--- +erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + CUSTOMER }|..|{ DELIVERY-ADDRESS : uses +``` +`````` + ```note Note that the site needs to use mermaid version 9.4+ for this to work and have this featured enabled in the lazy-loading configuration. ``` From 9795b6e089c6dfeadfaccd2453a0659f77292b88 Mon Sep 17 00:00:00 2001 From: Thomas Di Cizerone Date: Sun, 23 Mar 2025 22:12:35 +0100 Subject: [PATCH 27/50] =?UTF-8?q?=F0=9F=96=8B=EF=B8=8F=20Refactor=20common?= =?UTF-8?q?=20grammar=20to=20avoid=20unwanted=20greedy=20terminals?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/language/architecture/arch.langium | 2 + .../architecture/architecture.langium | 21 ++++---- .../parser/src/language/common/common.langium | 33 +++++++++---- .../src/language/gitGraph/gitGraph.langium | 49 ++++--------------- .../src/language/gitGraph/reference.langium | 4 ++ packages/parser/src/language/index.ts | 1 - .../parser/src/language/packet/packet.langium | 13 ++--- packages/parser/src/language/pie/pie.langium | 13 ++--- .../parser/src/language/radar/radar.langium | 40 ++------------- 9 files changed, 60 insertions(+), 116 deletions(-) create mode 100644 packages/parser/src/language/architecture/arch.langium create mode 100644 packages/parser/src/language/gitGraph/reference.langium diff --git a/packages/parser/src/language/architecture/arch.langium b/packages/parser/src/language/architecture/arch.langium new file mode 100644 index 000000000..7b3a2fe22 --- /dev/null +++ b/packages/parser/src/language/architecture/arch.langium @@ -0,0 +1,2 @@ +terminal ARCH_ICON: /\([\w-:]+\)/; +terminal ARCH_TITLE: /\[[\w ]+\]/; \ No newline at end of file diff --git a/packages/parser/src/language/architecture/architecture.langium b/packages/parser/src/language/architecture/architecture.langium index 11af26243..2e97372bd 100644 --- a/packages/parser/src/language/architecture/architecture.langium +++ b/packages/parser/src/language/architecture/architecture.langium @@ -1,14 +1,15 @@ grammar Architecture import "../common/common"; +import "arch"; entry Architecture: NEWLINE* "architecture-beta" ( - NEWLINE* TitleAndAccessibilities - | NEWLINE* Statement* - | NEWLINE* - ) + NEWLINE + | TitleAndAccessibilities + | Statement + )* ; fragment Statement: @@ -31,25 +32,21 @@ fragment Arrow: ; Group: - 'group' id=ARCH_ID icon=ARCH_ICON? title=ARCH_TITLE? ('in' in=ARCH_ID)? EOL + 'group' id=ID icon=ARCH_ICON? title=ARCH_TITLE? ('in' in=ID)? EOL ; Service: - 'service' id=ARCH_ID (iconText=ARCH_TEXT_ICON | icon=ARCH_ICON)? title=ARCH_TITLE? ('in' in=ARCH_ID)? EOL + 'service' id=ID (iconText=STRING | icon=ARCH_ICON)? title=ARCH_TITLE? ('in' in=ID)? EOL ; Junction: - 'junction' id=ARCH_ID ('in' in=ARCH_ID)? EOL + 'junction' id=ID ('in' in=ID)? EOL ; Edge: - lhsId=ARCH_ID lhsGroup?=ARROW_GROUP? Arrow rhsId=ARCH_ID rhsGroup?=ARROW_GROUP? EOL + lhsId=ID lhsGroup?=ARROW_GROUP? Arrow rhsId=ID rhsGroup?=ARROW_GROUP? EOL ; terminal ARROW_DIRECTION: 'L' | 'R' | 'T' | 'B'; -terminal ARCH_ID: /[\w]+/; -terminal ARCH_TEXT_ICON: /\("[^"]+"\)/; -terminal ARCH_ICON: /\([\w-:]+\)/; -terminal ARCH_TITLE: /\[[\w ]+\]/; terminal ARROW_GROUP: /\{group\}/; terminal ARROW_INTO: /<|>/; diff --git a/packages/parser/src/language/common/common.langium b/packages/parser/src/language/common/common.langium index 7989de193..e86fbadfe 100644 --- a/packages/parser/src/language/common/common.langium +++ b/packages/parser/src/language/common/common.langium @@ -1,22 +1,35 @@ -interface Common { - accDescr?: string; - accTitle?: string; - title?: string; -} - -fragment TitleAndAccessibilities: - ((accDescr=ACC_DESCR | accTitle=ACC_TITLE | title=TITLE) EOL)+ -; +// Base terminals and fragments for common language constructs +// Terminal Precedence: Lazy to Greedy +// When imported, the terminals are considered after the terminals in the importing grammar +// Note: Hence, to add a terminal greedier than the common terminals, import the common grammar first fragment EOL returns string: NEWLINE+ | EOF ; -terminal NEWLINE: /\r?\n/; +fragment TitleAndAccessibilities: + ((accDescr=ACC_DESCR | accTitle=ACC_TITLE | title=TITLE) EOL)+ +; + +terminal BOOLEAN returns boolean: 'true' | 'false'; + terminal ACC_DESCR: /[\t ]*accDescr(?:[\t ]*:([^\n\r]*?(?=%%)|[^\n\r]*)|\s*{([^}]*)})/; terminal ACC_TITLE: /[\t ]*accTitle[\t ]*:(?:[^\n\r]*?(?=%%)|[^\n\r]*)/; terminal TITLE: /[\t ]*title(?:[\t ][^\n\r]*?(?=%%)|[\t ][^\n\r]*|)/; +terminal FLOAT returns number: /[0-9]+\.[0-9]+(?!\.)/; +terminal INT returns number: /0|[1-9][0-9]*(?!\.)/; +terminal NUMBER returns number: FLOAT | INT; + +terminal STRING returns string: /"([^"\\]|\\.)*"|'([^'\\]|\\.)*'/; + +// Alphanumerics with underscores and dashes +// Must start with an alphanumeric or an underscore +// Cant end with a dash +terminal ID returns string: /[\w]([-\w]*\w)?/; + +terminal NEWLINE: /\r?\n/; + hidden terminal WHITESPACE: /[\t ]+/; hidden terminal YAML: /---[\t ]*\r?\n(?:[\S\s]*?\r?\n)?---(?:\r?\n|(?!\S))/; hidden terminal DIRECTIVE: /[\t ]*%%{[\S\s]*?}%%(?:\r?\n|(?!\S))/; diff --git a/packages/parser/src/language/gitGraph/gitGraph.langium b/packages/parser/src/language/gitGraph/gitGraph.langium index 1571ebba8..5a4b0596c 100644 --- a/packages/parser/src/language/gitGraph/gitGraph.langium +++ b/packages/parser/src/language/gitGraph/gitGraph.langium @@ -1,39 +1,15 @@ grammar GitGraph - -interface Common { - accDescr?: string; - accTitle?: string; - title?: string; -} - -fragment TitleAndAccessibilities: - ((accDescr=ACC_DESCR | accTitle=ACC_TITLE | title=TITLE) EOL)+ -; - -fragment EOL returns string: - NEWLINE+ | EOF -; - -terminal NEWLINE: /\r?\n/; -terminal ACC_DESCR: /[\t ]*accDescr(?:[\t ]*:([^\n\r]*?(?=%%)|[^\n\r]*)|\s*{([^}]*)})/; -terminal ACC_TITLE: /[\t ]*accTitle[\t ]*:(?:[^\n\r]*?(?=%%)|[^\n\r]*)/; -terminal TITLE: /[\t ]*title(?:[\t ][^\n\r]*?(?=%%)|[\t ][^\n\r]*|)/; - -hidden terminal WHITESPACE: /[\t ]+/; -hidden terminal YAML: /---[\t ]*\r?\n(?:[\S\s]*?\r?\n)?---(?:\r?\n|(?!\S))/; -hidden terminal DIRECTIVE: /[\t ]*%%{[\S\s]*?}%%(?:\r?\n|(?!\S))/; -hidden terminal SINGLE_LINE_COMMENT: /[\t ]*%%[^\n\r]*/; +import "../common/common"; +import "reference"; entry GitGraph: NEWLINE* ('gitGraph' | 'gitGraph' ':' | 'gitGraph:' | ('gitGraph' Direction ':')) - NEWLINE* ( - NEWLINE* - (TitleAndAccessibilities | - statements+=Statement | - NEWLINE)* - ) + NEWLINE + | TitleAndAccessibilities + | statements+=Statement + )* ; Statement @@ -56,12 +32,12 @@ Commit: |'type:' type=('NORMAL' | 'REVERSE' | 'HIGHLIGHT') )* EOL; Branch: - 'branch' name=(ID|STRING) + 'branch' name=(REFERENCE|STRING) ('order:' order=INT)? EOL; Merge: - 'merge' branch=(ID|STRING) + 'merge' branch=(REFERENCE|STRING) ( 'id:' id=STRING |'tag:' tags+=STRING @@ -69,7 +45,7 @@ Merge: )* EOL; Checkout: - ('checkout'|'switch') branch=(ID|STRING) EOL; + ('checkout'|'switch') branch=(REFERENCE|STRING) EOL; CherryPicking: 'cherry-pick' @@ -78,10 +54,3 @@ CherryPicking: |'tag:' tags+=STRING |'parent:' parent=STRING )* EOL; - - - -terminal INT returns number: /[0-9]+(?=\s)/; -terminal ID returns string: /\w([-\./\w]*[-\w])?/; -terminal STRING: /"[^"]*"|'[^']*'/; - diff --git a/packages/parser/src/language/gitGraph/reference.langium b/packages/parser/src/language/gitGraph/reference.langium new file mode 100644 index 000000000..6e1af5863 --- /dev/null +++ b/packages/parser/src/language/gitGraph/reference.langium @@ -0,0 +1,4 @@ +// Alphanumerics with underscores, dashes, slashes, and dots +// Must start with an alphanumeric or an underscore +// Cant end with a dash, slash, or dot +terminal REFERENCE returns string: /\w([-\./\w]*[-\w])?/; \ No newline at end of file diff --git a/packages/parser/src/language/index.ts b/packages/parser/src/language/index.ts index e3aa5c68c..aa0c0f703 100644 --- a/packages/parser/src/language/index.ts +++ b/packages/parser/src/language/index.ts @@ -12,7 +12,6 @@ export { Commit, Merge, Statement, - isCommon, isInfo, isPacket, isPacketBlock, diff --git a/packages/parser/src/language/packet/packet.langium b/packages/parser/src/language/packet/packet.langium index ad30f8df2..91d6501ed 100644 --- a/packages/parser/src/language/packet/packet.langium +++ b/packages/parser/src/language/packet/packet.langium @@ -5,15 +5,12 @@ entry Packet: NEWLINE* "packet-beta" ( - NEWLINE* TitleAndAccessibilities blocks+=PacketBlock* - | NEWLINE+ blocks+=PacketBlock+ - | NEWLINE* - ) + TitleAndAccessibilities + | blocks+=PacketBlock + | NEWLINE + )* ; PacketBlock: start=INT('-' end=INT)? ':' label=STRING EOL -; - -terminal INT returns number: /0|[1-9][0-9]*/; -terminal STRING: /"[^"]*"|'[^']*'/; +; \ No newline at end of file diff --git a/packages/parser/src/language/pie/pie.langium b/packages/parser/src/language/pie/pie.langium index 2bbf967e1..a80caa81f 100644 --- a/packages/parser/src/language/pie/pie.langium +++ b/packages/parser/src/language/pie/pie.langium @@ -5,15 +5,12 @@ entry Pie: NEWLINE* "pie" showData?="showData"? ( - NEWLINE* TitleAndAccessibilities sections+=PieSection* - | NEWLINE+ sections+=PieSection+ - | NEWLINE* - ) + TitleAndAccessibilities + | sections+=PieSection + | NEWLINE + )* ; PieSection: - label=PIE_SECTION_LABEL ":" value=PIE_SECTION_VALUE EOL + label=STRING ":" value=NUMBER EOL ; - -terminal PIE_SECTION_LABEL: /"[^"]+"/; -terminal PIE_SECTION_VALUE returns number: /(0|[1-9][0-9]*)(\.[0-9]+)?/; diff --git a/packages/parser/src/language/radar/radar.langium b/packages/parser/src/language/radar/radar.langium index f0ecd13cd..8aa9cb0ff 100644 --- a/packages/parser/src/language/radar/radar.langium +++ b/packages/parser/src/language/radar/radar.langium @@ -1,31 +1,5 @@ grammar Radar -// import "../common/common"; -// Note: The import statement breaks TitleAndAccessibilities probably because of terminal order definition -// TODO: May need to change the common.langium to fix this - -interface Common { - accDescr?: string; - accTitle?: string; - title?: string; -} - -fragment TitleAndAccessibilities: - ((accDescr=ACC_DESCR | accTitle=ACC_TITLE | title=TITLE) EOL)+ -; - -fragment EOL returns string: - NEWLINE+ | EOF -; - -terminal NEWLINE: /\r?\n/; -terminal ACC_DESCR: /[\t ]*accDescr(?:[\t ]*:([^\n\r]*?(?=%%)|[^\n\r]*)|\s*{([^}]*)})/; -terminal ACC_TITLE: /[\t ]*accTitle[\t ]*:(?:[^\n\r]*?(?=%%)|[^\n\r]*)/; -terminal TITLE: /[\t ]*title(?:[\t ][^\n\r]*?(?=%%)|[\t ][^\n\r]*|)/; - -hidden terminal WHITESPACE: /[\t ]+/; -hidden terminal YAML: /---[\t ]*\r?\n(?:[\S\s]*?\r?\n)?---(?:\r?\n|(?!\S))/; -hidden terminal DIRECTIVE: /[\t ]*%%{[\S\s]*?}%%(?:\r?\n|(?!\S))/; -hidden terminal SINGLE_LINE_COMMENT: /[\t ]*%%[^\n\r]*/; +import "../common/common"; entry Radar: NEWLINE* @@ -76,14 +50,6 @@ Option: | name='min' value=NUMBER | name='graticule' value=GRATICULE ) -; +; - -terminal NUMBER returns number: /(0|[1-9][0-9]*)(\.[0-9]+)?/; - -terminal BOOLEAN returns boolean: 'true' | 'false'; - -terminal GRATICULE returns string: 'circle' | 'polygon'; - -terminal ID returns string: /[a-zA-Z_][a-zA-Z0-9\-_]*/; -terminal STRING: /"[^"]*"|'[^']*'/; \ No newline at end of file +terminal GRATICULE returns string: 'circle' | 'polygon'; \ No newline at end of file From 04d68e7f9a23b9fcc051385ca91d6e401e26e9ba Mon Sep 17 00:00:00 2001 From: Thomas Di Cizerone Date: Sun, 23 Mar 2025 22:15:37 +0100 Subject: [PATCH 28/50] =?UTF-8?q?=E2=9A=97=EF=B8=8F=20Add=20parser=20tests?= =?UTF-8?q?=20for=20architecture=20and=20other=20edge=20cases=20encountere?= =?UTF-8?q?d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/parser/tests/architecture.test.ts | 88 +++++ packages/parser/tests/gitGraph.test.ts | 6 + packages/parser/tests/pie.test.ts | 353 +++++++++++---------- packages/parser/tests/test-util.ts | 14 + 4 files changed, 295 insertions(+), 166 deletions(-) create mode 100644 packages/parser/tests/architecture.test.ts diff --git a/packages/parser/tests/architecture.test.ts b/packages/parser/tests/architecture.test.ts new file mode 100644 index 000000000..4dcce17d3 --- /dev/null +++ b/packages/parser/tests/architecture.test.ts @@ -0,0 +1,88 @@ +import { describe, expect, it } from 'vitest'; + +import { Architecture } from '../src/language/index.js'; +import { expectNoErrorsOrAlternatives, architectureParse as parse } from './test-util.js'; + +describe('architecture', () => { + describe('should handle architecture definition', () => { + it.each([ + `architecture-beta`, + ` architecture-beta `, + `\tarchitecture-beta\t`, + ` + \tarchitecture-beta + `, + ])('should handle regular architecture', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + }); + }); + + describe('should handle TitleAndAccessibilities', () => { + it.each([ + `architecture-beta title sample title`, + ` architecture-beta title sample title `, + `\tarchitecture-beta\ttitle sample title\t`, + `architecture-beta + \ttitle sample title + `, + ])('should handle regular architecture + title in same line', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + + const { title } = result.value; + expect(title).toBe('sample title'); + }); + + it.each([ + `architecture-beta + title sample title`, + `architecture-beta + title sample title + `, + ])('should handle regular architecture + title in next line', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + + const { title } = result.value; + expect(title).toBe('sample title'); + }); + + it('should handle regular architecture + title + accTitle + accDescr', () => { + const context = `architecture-beta + title sample title + accTitle: sample accTitle + accDescr: sample accDescr + `; + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + + const { title, accTitle, accDescr } = result.value; + expect(title).toBe('sample title'); + expect(accTitle).toBe('sample accTitle'); + expect(accDescr).toBe('sample accDescr'); + }); + + it('should handle regular architecture + title + accTitle + multi-line accDescr', () => { + const context = `architecture-beta + title sample title + accTitle: sample accTitle + accDescr { + sample accDescr + } + `; + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + + const { title, accTitle, accDescr } = result.value; + expect(title).toBe('sample title'); + expect(accTitle).toBe('sample accTitle'); + expect(accDescr).toBe('sample accDescr'); + }); + }); +}); diff --git a/packages/parser/tests/gitGraph.test.ts b/packages/parser/tests/gitGraph.test.ts index 2d7c21bbe..f7f302236 100644 --- a/packages/parser/tests/gitGraph.test.ts +++ b/packages/parser/tests/gitGraph.test.ts @@ -63,6 +63,12 @@ describe('Parsing Branch Statements', () => { expect(branch.name).toBe('master'); }); + it('should parse a branch name starting with numbers', () => { + const result = parse(`gitGraph\n commit\n branch 1.0.1\n`); + const branch = result.value.statements[1] as Branch; + expect(branch.name).toBe('1.0.1'); + }); + it('should parse a branch with an order property', () => { const result = parse(`gitGraph\n commit\n branch feature order:1\n`); const branch = result.value.statements[1] as Branch; diff --git a/packages/parser/tests/pie.test.ts b/packages/parser/tests/pie.test.ts index 43e9a374f..caa7cc528 100644 --- a/packages/parser/tests/pie.test.ts +++ b/packages/parser/tests/pie.test.ts @@ -4,226 +4,247 @@ import { Pie } from '../src/language/index.js'; import { expectNoErrorsOrAlternatives, pieParse as parse } from './test-util.js'; describe('pie', () => { - it.each([ - `pie`, - ` pie `, - `\tpie\t`, - ` + describe('should handle pie definition with or without showData', () => { + it.each([ + `pie`, + ` pie `, + `\tpie\t`, + ` \tpie `, - ])('should handle regular pie', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); - }); + ])('should handle regular pie', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); + }); - it.each([ - `pie showData`, - ` pie showData `, - `\tpie\tshowData\t`, - ` + it.each([ + `pie showData`, + ` pie showData `, + `\tpie\tshowData\t`, + ` pie\tshowData `, - ])('should handle regular showData', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + ])('should handle regular showData', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { showData } = result.value; - expect(showData).toBeTruthy(); + const { showData } = result.value; + expect(showData).toBeTruthy(); + }); }); + describe('should handle TitleAndAccessibilities', () => { + describe('should handle TitleAndAccessibilities without showData', () => { + it.each([ + `pie title sample title`, + ` pie title sample title `, + `\tpie\ttitle sample title\t`, + `pie + \ttitle sample title + `, + ])('should handle regular pie + title in same line', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - it.each([ - `pie title sample title`, - ` pie title sample title `, - `\tpie\ttitle sample title\t`, - `pie - \ttitle sample title - `, - ])('should handle regular pie + title in same line', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const { title } = result.value; + expect(title).toBe('sample title'); + }); - const { title } = result.value; - expect(title).toBe('sample title'); - }); - - it.each([ - `pie - title sample title`, - `pie - title sample title - `, - `pie - title sample title`, - `pie - title sample title - `, - ])('should handle regular pie + title in different line', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); - - const { title } = result.value; - expect(title).toBe('sample title'); - }); - - it.each([ - `pie showData title sample title`, - `pie showData title sample title - `, - ])('should handle regular pie + showData + title', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); - - const { showData, title } = result.value; - expect(showData).toBeTruthy(); - expect(title).toBe('sample title'); - }); - - it.each([ - `pie showData - title sample title`, - `pie showData - title sample title - `, - `pie showData - title sample title`, - `pie showData - title sample title - `, - ])('should handle regular showData + title in different line', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); - - const { showData, title } = result.value; - expect(showData).toBeTruthy(); - expect(title).toBe('sample title'); - }); - - describe('sections', () => { - describe('normal', () => { it.each([ `pie + title sample title`, + `pie + title sample title + `, + `pie + title sample title`, + `pie + title sample title + `, + ])('should handle regular pie + title in different line', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); + + const { title } = result.value; + expect(title).toBe('sample title'); + }); + }); + + describe('should handle TitleAndAccessibilities with showData', () => { + it.each([ + `pie showData title sample title`, + `pie showData title sample title + `, + ])('should handle regular pie + showData + title', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); + + const { showData, title } = result.value; + expect(showData).toBeTruthy(); + expect(title).toBe('sample title'); + }); + + it.each([ + `pie showData + title sample title`, + `pie showData + title sample title + `, + `pie showData + title sample title`, + `pie showData + title sample title + `, + ])('should handle regular showData + title in different line', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); + + const { showData, title } = result.value; + expect(showData).toBeTruthy(); + expect(title).toBe('sample title'); + }); + }); + }); + + describe('should handle sections', () => { + it.each([ + `pie "GitHub":100 "GitLab":50`, - `pie + `pie "GitHub" : 100 "GitLab" : 50`, - `pie + `pie "GitHub"\t:\t100 "GitLab"\t:\t50`, - `pie + `pie \t"GitHub" \t : \t 100 \t"GitLab" \t : \t 50 `, - ])('should handle regular sections', (context: string) => { - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + ])('should handle regular sections', (context: string) => { + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { sections } = result.value; - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + const { sections } = result.value; + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); + }); - it('should handle sections with showData', () => { - const context = `pie showData + it('should handle sections with showData', () => { + const context = `pie showData "GitHub": 100 "GitLab": 50`; - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { showData, sections } = result.value; - expect(showData).toBeTruthy(); + const { showData, sections } = result.value; + expect(showData).toBeTruthy(); - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); + }); - it('should handle sections with title', () => { - const context = `pie title sample wow + it('should handle sections with title', () => { + const context = `pie title sample wow "GitHub": 100 "GitLab": 50`; - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { title, sections } = result.value; - expect(title).toBe('sample wow'); + const { title, sections } = result.value; + expect(title).toBe('sample wow'); - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); + }); - it('should handle sections with accTitle', () => { - const context = `pie accTitle: sample wow + it('should handle value with positive decimal', () => { + const context = `pie + "ash": 60.67 + "bat": 40`; + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); + + const { sections } = result.value; + expect(sections[0].label).toBe('ash'); + expect(sections[0].value).toBe(60.67); + + expect(sections[1].label).toBe('bat'); + expect(sections[1].value).toBe(40); + }); + + it('should handle sections with accTitle', () => { + const context = `pie accTitle: sample wow "GitHub": 100 "GitLab": 50`; - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { accTitle, sections } = result.value; - expect(accTitle).toBe('sample wow'); + const { accTitle, sections } = result.value; + expect(accTitle).toBe('sample wow'); - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); + }); - it('should handle sections with single line accDescr', () => { - const context = `pie accDescr: sample wow + it('should handle sections with single line accDescr', () => { + const context = `pie accDescr: sample wow "GitHub": 100 "GitLab": 50`; - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { accDescr, sections } = result.value; - expect(accDescr).toBe('sample wow'); + const { accDescr, sections } = result.value; + expect(accDescr).toBe('sample wow'); - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); + }); - it('should handle sections with multi line accDescr', () => { - const context = `pie accDescr { + it('should handle sections with multi line accDescr', () => { + const context = `pie accDescr { sample wow } "GitHub": 100 "GitLab": 50`; - const result = parse(context); - expectNoErrorsOrAlternatives(result); - expect(result.value.$type).toBe(Pie); + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Pie); - const { accDescr, sections } = result.value; - expect(accDescr).toBe('sample wow'); + const { accDescr, sections } = result.value; + expect(accDescr).toBe('sample wow'); - expect(sections[0].label).toBe('GitHub'); - expect(sections[0].value).toBe(100); + expect(sections[0].label).toBe('GitHub'); + expect(sections[0].value).toBe(100); - expect(sections[1].label).toBe('GitLab'); - expect(sections[1].value).toBe(50); - }); + expect(sections[1].label).toBe('GitLab'); + expect(sections[1].value).toBe(50); }); }); }); diff --git a/packages/parser/tests/test-util.ts b/packages/parser/tests/test-util.ts index bc2224e65..7a6050016 100644 --- a/packages/parser/tests/test-util.ts +++ b/packages/parser/tests/test-util.ts @@ -1,6 +1,8 @@ import type { LangiumParser, ParseResult } from 'langium'; import { expect, vi } from 'vitest'; import type { + Architecture, + ArchitectureServices, Info, InfoServices, Pie, @@ -13,6 +15,7 @@ import type { GitGraphServices, } from '../src/language/index.js'; import { + createArchitectureServices, createInfoServices, createPieServices, createRadarServices, @@ -47,6 +50,17 @@ export function createInfoTestServices() { } export const infoParse = createInfoTestServices().parse; +const architectureServices: ArchitectureServices = createArchitectureServices().Architecture; +const architectureParser: LangiumParser = architectureServices.parser.LangiumParser; +export function createArchitectureTestServices() { + const parse = (input: string) => { + return architectureParser.parse(input); + }; + + return { services: architectureServices, parse }; +} +export const architectureParse = createArchitectureTestServices().parse; + const pieServices: PieServices = createPieServices().Pie; const pieParser: LangiumParser = pieServices.parser.LangiumParser; export function createPieTestServices() { From e588743bf45439cb2fff3fe2fb9a787a9fb0e4eb Mon Sep 17 00:00:00 2001 From: Thomas Di Cizerone Date: Sun, 23 Mar 2025 22:20:26 +0100 Subject: [PATCH 29/50] =?UTF-8?q?=E2=9A=97=EF=B8=8F=20Add=20unit=20tests?= =?UTF-8?q?=20and=20e2e=20for=20architecture=20diagram=20with=20titleAndAc?= =?UTF-8?q?cessibilities?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rendering/architecture.spec.ts | 21 +++++- .../architecture/architecture.spec.ts | 70 +++++++++++++++++++ .../diagrams/architecture/architectureDb.ts | 18 +++-- .../architecture/architectureTypes.ts | 4 +- .../mermaid/src/diagrams/radar/radar.spec.ts | 4 +- packages/mermaid/src/mermaidAPI.spec.ts | 2 + 6 files changed, 107 insertions(+), 12 deletions(-) create mode 100644 packages/mermaid/src/diagrams/architecture/architecture.spec.ts diff --git a/cypress/integration/rendering/architecture.spec.ts b/cypress/integration/rendering/architecture.spec.ts index 25326ff80..ec74a5dd5 100644 --- a/cypress/integration/rendering/architecture.spec.ts +++ b/cypress/integration/rendering/architecture.spec.ts @@ -19,6 +19,25 @@ describe.skip('architecture diagram', () => { ` ); }); + it('should render a simple architecture diagram with titleAndAccessabilities', () => { + imgSnapshotTest( + `architecture-beta + title Simple Architecture Diagram + accTitle: Accessibility Title + accDescr: Accessibility Description + group api(cloud)[API] + + service db(database)[Database] in api + service disk1(disk)[Storage] in api + service disk2(disk)[Storage] in api + service server(server)[Server] in api + + db:L -- R:server + disk1:T -- B:server + disk2:T -- B:db + ` + ); + }); it('should render an architecture diagram with groups within groups', () => { imgSnapshotTest( `architecture-beta @@ -172,7 +191,7 @@ describe.skip('architecture diagram', () => { ); }); - it('should render an architecture diagram with a resonable height', () => { + it('should render an architecture diagram with a reasonable height', () => { imgSnapshotTest( `architecture-beta group federated(cloud)[Federated Environment] diff --git a/packages/mermaid/src/diagrams/architecture/architecture.spec.ts b/packages/mermaid/src/diagrams/architecture/architecture.spec.ts new file mode 100644 index 000000000..45c19e23e --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architecture.spec.ts @@ -0,0 +1,70 @@ +import { it, describe, expect } from 'vitest'; +import { db } from './architectureDb.js'; +import { parser } from './architectureParser.js'; + +const { + clear, + getDiagramTitle, + getAccTitle, + getAccDescription, + getServices, + getGroups, + getEdges, + getJunctions, +} = db; + +describe('architecture diagrams', () => { + beforeEach(() => { + clear(); + }); + + describe('architecture diagram definitions', () => { + it('should handle the architecture keyword', async () => { + const str = `architecture-beta`; + await expect(parser.parse(str)).resolves.not.toThrow(); + }); + + it('should handle an simple radar definition', async () => { + const str = `architecture-beta + service db + `; + await expect(parser.parse(str)).resolves.not.toThrow(); + }); + }); + + describe('should handle TitleAndAccessibilities', () => { + it('should handle title on the first line', async () => { + const str = `architecture-beta title Simple Architecture Diagram`; + await expect(parser.parse(str)).resolves.not.toThrow(); + expect(getDiagramTitle()).toBe('Simple Architecture Diagram'); + }); + + it('should handle title on another line', async () => { + const str = `architecture-beta + title Simple Architecture Diagram + `; + await expect(parser.parse(str)).resolves.not.toThrow(); + expect(getDiagramTitle()).toBe('Simple Architecture Diagram'); + }); + + it('should handle accessibility title and description', async () => { + const str = `architecture-beta + accTitle: Accessibility Title + accDescr: Accessibility Description + `; + await expect(parser.parse(str)).resolves.not.toThrow(); + expect(getAccTitle()).toBe('Accessibility Title'); + expect(getAccDescription()).toBe('Accessibility Description'); + }); + + it('should handle multiline accessibility description', async () => { + const str = `architecture-beta + accDescr { + Accessibility Description + } + `; + await expect(parser.parse(str)).resolves.not.toThrow(); + expect(getAccDescription()).toBe('Accessibility Description'); + }); + }); +}); diff --git a/packages/mermaid/src/diagrams/architecture/architectureDb.ts b/packages/mermaid/src/diagrams/architecture/architectureDb.ts index 2174ebe19..c7bd64e21 100644 --- a/packages/mermaid/src/diagrams/architecture/architectureDb.ts +++ b/packages/mermaid/src/diagrams/architecture/architectureDb.ts @@ -1,6 +1,6 @@ import type { ArchitectureDiagramConfig } from '../../config.type.js'; import DEFAULT_CONFIG from '../../defaultConfig.js'; -import { getConfig } from '../../diagram-api/diagramAPI.js'; +import { getConfig as commonGetConfig } from '../../config.js'; import type { D3Element } from '../../types.js'; import { ImperativeState } from '../../utils/imperativeState.js'; import { @@ -33,6 +33,7 @@ import { isArchitectureService, shiftPositionByArchitectureDirectionPair, } from './architectureTypes.js'; +import { cleanAndMerge } from '../../utils.js'; const DEFAULT_ARCHITECTURE_CONFIG: Required = DEFAULT_CONFIG.architecture; @@ -316,6 +317,14 @@ const setElementForId = (id: string, element: D3Element) => { }; const getElementById = (id: string) => state.records.elements[id]; +const getConfig = (): Required => { + const config = cleanAndMerge({ + ...DEFAULT_ARCHITECTURE_CONFIG, + ...commonGetConfig().architecture, + }); + return config; +}; + export const db: ArchitectureDB = { clear, setDiagramTitle, @@ -324,6 +333,7 @@ export const db: ArchitectureDB = { getAccTitle, setAccDescription, getAccDescription, + getConfig, addService, getServices, @@ -348,9 +358,5 @@ export const db: ArchitectureDB = { export function getConfigField( field: T ): Required[T] { - const arch = getConfig().architecture; - if (arch?.[field]) { - return arch[field] as Required[T]; - } - return DEFAULT_ARCHITECTURE_CONFIG[field]; + return getConfig()[field]; } diff --git a/packages/mermaid/src/diagrams/architecture/architectureTypes.ts b/packages/mermaid/src/diagrams/architecture/architectureTypes.ts index a7af33ca7..c61df11ff 100644 --- a/packages/mermaid/src/diagrams/architecture/architectureTypes.ts +++ b/packages/mermaid/src/diagrams/architecture/architectureTypes.ts @@ -1,4 +1,4 @@ -import type { DiagramDB } from '../../diagram-api/types.js'; +import type { DiagramDBBase } from '../../diagram-api/types.js'; import type { ArchitectureDiagramConfig } from '../../config.type.js'; import type { D3Element } from '../../types.js'; import type cytoscape from 'cytoscape'; @@ -242,7 +242,7 @@ export interface ArchitectureEdge
{ title?: string; } -export interface ArchitectureDB extends DiagramDB { +export interface ArchitectureDB extends DiagramDBBase { clear: () => void; addService: (service: Omit) => void; getServices: () => ArchitectureService[]; diff --git a/packages/mermaid/src/diagrams/radar/radar.spec.ts b/packages/mermaid/src/diagrams/radar/radar.spec.ts index 5e5f444c6..3a506c69e 100644 --- a/packages/mermaid/src/diagrams/radar/radar.spec.ts +++ b/packages/mermaid/src/diagrams/radar/radar.spec.ts @@ -1,11 +1,9 @@ import { it, describe, expect } from 'vitest'; import { db } from './db.js'; import { parser } from './parser.js'; -import { renderer, relativeRadius, closedRoundCurve } from './renderer.js'; +import { relativeRadius, closedRoundCurve } from './renderer.js'; import { Diagram } from '../../Diagram.js'; import mermaidAPI from '../../mermaidAPI.js'; -import { a } from 'vitest/dist/chunks/suite.qtkXWc6R.js'; -import { buildRadarStyleOptions } from './styles.js'; const { clear, diff --git a/packages/mermaid/src/mermaidAPI.spec.ts b/packages/mermaid/src/mermaidAPI.spec.ts index 64f4b8d60..6b112b90e 100644 --- a/packages/mermaid/src/mermaidAPI.spec.ts +++ b/packages/mermaid/src/mermaidAPI.spec.ts @@ -31,6 +31,7 @@ vi.mock('./diagrams/xychart/xychartRenderer.js'); vi.mock('./diagrams/requirement/requirementRenderer.js'); vi.mock('./diagrams/sequence/sequenceRenderer.js'); vi.mock('./diagrams/radar/renderer.js'); +vi.mock('./diagrams/architecture/architectureRenderer.js'); // ------------------------------------- @@ -799,6 +800,7 @@ graph TD;A--x|text including URL space|B;`) { textDiagramType: 'sequenceDiagram', expectedType: 'sequence' }, { textDiagramType: 'stateDiagram-v2', expectedType: 'stateDiagram' }, { textDiagramType: 'radar-beta', expectedType: 'radar' }, + { textDiagramType: 'architecture-beta', expectedType: 'architecture' }, ]; describe('accessibility', () => { From fd4493733f542adb763b12e14c5e879540e6866f Mon Sep 17 00:00:00 2001 From: Thomas Di Cizerone Date: Sun, 23 Mar 2025 22:36:40 +0100 Subject: [PATCH 30/50] =?UTF-8?q?=E2=8F=B0=20Add=20TODO=20for=20architectu?= =?UTF-8?q?re=20support=20of=20title=20embedded=20in=20render?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mermaid/src/diagrams/architecture/architectureRenderer.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts b/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts index 768c174b0..9479e5108 100644 --- a/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts +++ b/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts @@ -500,6 +500,8 @@ function layoutArchitecture( } export const draw: DrawDefinition = async (text, id, _version, diagObj: Diagram) => { + // TODO: Add title support for architecture diagrams + const db = diagObj.db as ArchitectureDB; const services = db.getServices(); From 630c4d6954e048dd2795fedc5026b9c30473e6a5 Mon Sep 17 00:00:00 2001 From: Thomas Di Cizerone Date: Sun, 23 Mar 2025 22:50:20 +0100 Subject: [PATCH 31/50] =?UTF-8?q?=F0=9F=A4=8F=20Update=20Note=20comment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/parser/src/language/common/common.langium | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/parser/src/language/common/common.langium b/packages/parser/src/language/common/common.langium index e86fbadfe..b74ffc34d 100644 --- a/packages/parser/src/language/common/common.langium +++ b/packages/parser/src/language/common/common.langium @@ -1,7 +1,7 @@ // Base terminals and fragments for common language constructs // Terminal Precedence: Lazy to Greedy // When imported, the terminals are considered after the terminals in the importing grammar -// Note: Hence, to add a terminal greedier than the common terminals, import the common grammar first +// Note: Hence, to add a terminal greedier than the common terminals, import it separately after the common import fragment EOL returns string: NEWLINE+ | EOF From cdbd3e58a3a35d63a79258115dedca4a535c1038 Mon Sep 17 00:00:00 2001 From: Thomas Di Cizerone Date: Sun, 23 Mar 2025 23:03:48 +0100 Subject: [PATCH 32/50] =?UTF-8?q?=F0=9F=86=99=20Run=20pnpm=20changeset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/sad-mails-accept.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/sad-mails-accept.md diff --git a/.changeset/sad-mails-accept.md b/.changeset/sad-mails-accept.md new file mode 100644 index 000000000..11dd69d8d --- /dev/null +++ b/.changeset/sad-mails-accept.md @@ -0,0 +1,6 @@ +--- +'mermaid': patch +'@mermaid-js/parser': patch +--- + +Refactor grammar so that title don't break Architecture Diagrams From 9208e7faafa74e63b34884b4527fa7b3edb1a052 Mon Sep 17 00:00:00 2001 From: nour kouider Date: Fri, 4 Apr 2025 18:22:56 +0100 Subject: [PATCH 33/50] fix(docs): fix edge ID example --- docs/syntax/flowchart.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/syntax/flowchart.md b/docs/syntax/flowchart.md index 40ee2ef63..2e1a25b36 100644 --- a/docs/syntax/flowchart.md +++ b/docs/syntax/flowchart.md @@ -1229,13 +1229,13 @@ In the initial version, two animation speeds are supported: `fast` and `slow`. S ```mermaid-example flowchart LR - A e1@–> B + A e1@–-> B e1@{ animation: fast } ``` ```mermaid flowchart LR - A e1@–> B + A e1@–-> B e1@{ animation: fast } ``` @@ -1247,14 +1247,14 @@ You can also animate edges by assigning a class to them and then defining animat ```mermaid-example flowchart LR - A e1@–> B + A e1@–-> B classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; class e1 animate ``` ```mermaid flowchart LR - A e1@–> B + A e1@–-> B classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; class e1 animate ``` From 52cd9e8e5560ded5cfe343f9f1d82e80eac79109 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 4 Apr 2025 17:37:42 +0000 Subject: [PATCH 34/50] [autofix.ci] apply automated fixes --- docs/syntax/flowchart.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/syntax/flowchart.md b/docs/syntax/flowchart.md index 2e1a25b36..40ee2ef63 100644 --- a/docs/syntax/flowchart.md +++ b/docs/syntax/flowchart.md @@ -1229,13 +1229,13 @@ In the initial version, two animation speeds are supported: `fast` and `slow`. S ```mermaid-example flowchart LR - A e1@–-> B + A e1@–> B e1@{ animation: fast } ``` ```mermaid flowchart LR - A e1@–-> B + A e1@–> B e1@{ animation: fast } ``` @@ -1247,14 +1247,14 @@ You can also animate edges by assigning a class to them and then defining animat ```mermaid-example flowchart LR - A e1@–-> B + A e1@–> B classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; class e1 animate ``` ```mermaid flowchart LR - A e1@–-> B + A e1@–> B classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; class e1 animate ``` From 7facc8f50dcebee8a92f9c80c400ad4a77469af2 Mon Sep 17 00:00:00 2001 From: nour kouider Date: Fri, 4 Apr 2025 19:02:55 +0100 Subject: [PATCH 35/50] docs: fix edge ID example and regenerate flowchart output --- docs/syntax/flowchart.md | 12 ++++++------ packages/mermaid/src/docs/syntax/flowchart.md | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/syntax/flowchart.md b/docs/syntax/flowchart.md index 40ee2ef63..bfdda3710 100644 --- a/docs/syntax/flowchart.md +++ b/docs/syntax/flowchart.md @@ -1193,12 +1193,12 @@ To give an edge an ID, prepend the edge syntax with the ID followed by an `@` ch ```mermaid-example flowchart LR - A e1@–> B + A e1@–-> B ``` ```mermaid flowchart LR - A e1@–> B + A e1@–-> B ``` In this example, `e1` is the ID of the edge connecting `A` to `B`. You can then use this ID in later definitions or style statements, just like with nodes. @@ -1229,13 +1229,13 @@ In the initial version, two animation speeds are supported: `fast` and `slow`. S ```mermaid-example flowchart LR - A e1@–> B + A e1@–-> B e1@{ animation: fast } ``` ```mermaid flowchart LR - A e1@–> B + A e1@–-> B e1@{ animation: fast } ``` @@ -1247,14 +1247,14 @@ You can also animate edges by assigning a class to them and then defining animat ```mermaid-example flowchart LR - A e1@–> B + A e1@–-> B classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; class e1 animate ``` ```mermaid flowchart LR - A e1@–> B + A e1@–-> B classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; class e1 animate ``` diff --git a/packages/mermaid/src/docs/syntax/flowchart.md b/packages/mermaid/src/docs/syntax/flowchart.md index 2ddad4795..09637241a 100644 --- a/packages/mermaid/src/docs/syntax/flowchart.md +++ b/packages/mermaid/src/docs/syntax/flowchart.md @@ -721,7 +721,7 @@ To give an edge an ID, prepend the edge syntax with the ID followed by an `@` ch ```mermaid flowchart LR - A e1@–> B + A e1@–-> B ``` In this example, `e1` is the ID of the edge connecting `A` to `B`. You can then use this ID in later definitions or style statements, just like with nodes. @@ -746,7 +746,7 @@ In the initial version, two animation speeds are supported: `fast` and `slow`. S ```mermaid flowchart LR - A e1@–> B + A e1@–-> B e1@{ animation: fast } ``` @@ -758,7 +758,7 @@ You can also animate edges by assigning a class to them and then defining animat ```mermaid flowchart LR - A e1@–> B + A e1@–-> B classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; class e1 animate ``` From 4fdb1d5906059577037afa47733be36febf9487e Mon Sep 17 00:00:00 2001 From: nour kouider Date: Sat, 5 Apr 2025 13:39:30 +0100 Subject: [PATCH 36/50] docs: correct edge syntax from -> to --> --- docs/syntax/flowchart.md | 12 ++++++------ packages/mermaid/src/docs/syntax/flowchart.md | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/syntax/flowchart.md b/docs/syntax/flowchart.md index bfdda3710..20808c765 100644 --- a/docs/syntax/flowchart.md +++ b/docs/syntax/flowchart.md @@ -1193,12 +1193,12 @@ To give an edge an ID, prepend the edge syntax with the ID followed by an `@` ch ```mermaid-example flowchart LR - A e1@–-> B + A e1@--> B ``` ```mermaid flowchart LR - A e1@–-> B + A e1@--> B ``` In this example, `e1` is the ID of the edge connecting `A` to `B`. You can then use this ID in later definitions or style statements, just like with nodes. @@ -1229,13 +1229,13 @@ In the initial version, two animation speeds are supported: `fast` and `slow`. S ```mermaid-example flowchart LR - A e1@–-> B + A e1@--> B e1@{ animation: fast } ``` ```mermaid flowchart LR - A e1@–-> B + A e1@--> B e1@{ animation: fast } ``` @@ -1247,14 +1247,14 @@ You can also animate edges by assigning a class to them and then defining animat ```mermaid-example flowchart LR - A e1@–-> B + A e1@--> B classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; class e1 animate ``` ```mermaid flowchart LR - A e1@–-> B + A e1@--> B classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; class e1 animate ``` diff --git a/packages/mermaid/src/docs/syntax/flowchart.md b/packages/mermaid/src/docs/syntax/flowchart.md index 09637241a..f13dafba4 100644 --- a/packages/mermaid/src/docs/syntax/flowchart.md +++ b/packages/mermaid/src/docs/syntax/flowchart.md @@ -721,7 +721,7 @@ To give an edge an ID, prepend the edge syntax with the ID followed by an `@` ch ```mermaid flowchart LR - A e1@–-> B + A e1@--> B ``` In this example, `e1` is the ID of the edge connecting `A` to `B`. You can then use this ID in later definitions or style statements, just like with nodes. @@ -746,7 +746,7 @@ In the initial version, two animation speeds are supported: `fast` and `slow`. S ```mermaid flowchart LR - A e1@–-> B + A e1@--> B e1@{ animation: fast } ``` @@ -758,7 +758,7 @@ You can also animate edges by assigning a class to them and then defining animat ```mermaid flowchart LR - A e1@–-> B + A e1@--> B classDef animate stroke-dasharray: 9,5,stroke-dashoffset: 900,animation: dash 25s linear infinite; class e1 animate ``` From de72e18a7fa0894f9eac5c60670299dfc7a533fc Mon Sep 17 00:00:00 2001 From: Alois Klink Date: Mon, 7 Apr 2025 16:07:43 +0800 Subject: [PATCH 37/50] docs: improve elk section of ER docs --- docs/syntax/entityRelationshipDiagram.md | 36 ++++++++++++++++--- .../docs/syntax/entityRelationshipDiagram.md | 12 +++---- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/docs/syntax/entityRelationshipDiagram.md b/docs/syntax/entityRelationshipDiagram.md index 3dec08524..4ec776c10 100644 --- a/docs/syntax/entityRelationshipDiagram.md +++ b/docs/syntax/entityRelationshipDiagram.md @@ -625,17 +625,43 @@ erDiagram ## Configuration -### Renderer +### Layout -The layout of the diagram is done with the renderer. The default renderer is dagre. +The layout of the diagram is handled by [`render()`](../config/setup/mermaid/interfaces/Mermaid.md#render). The default layout is dagre. -You can opt to use an alternate renderer named elk by editing the configuration. The elk renderer is better for larger and/or more complex diagrams. +For larger or more-complex diagrams, you can alternatively apply the ELK (Eclipse Layout Kernel) layout using your YAML frontmatter's `config`. For more information, see [Customizing ELK Layout](../intro/syntax-reference.md#customizing-elk-layout). +```yaml +--- +config: + layout: elk +--- ``` + +Your Mermaid code should be similar to the following: + +```mermaid-example --- - config: - layout: elk +title: Order example +config: + layout: elk --- +erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + CUSTOMER }|..|{ DELIVERY-ADDRESS : uses +``` + +```mermaid +--- +title: Order example +config: + layout: elk +--- +erDiagram + CUSTOMER ||--o{ ORDER : places + ORDER ||--|{ LINE-ITEM : contains + CUSTOMER }|..|{ DELIVERY-ADDRESS : uses ``` > **Note** diff --git a/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md b/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md index cb0db0844..600d50723 100644 --- a/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md +++ b/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md @@ -407,23 +407,22 @@ erDiagram ## Configuration -### Renderer +### Layout The layout of the diagram is handled by [`render()`](../config/setup/mermaid/interfaces/Mermaid.md#render). The default layout is dagre. -For larger or more-complex diagrams, you can alternatively apply the ELK (Eclipse Layout Kernel) layout using your YAML frontmatter's `config`. For more information, see [Customizing ELK Layout](../intro/syntax-reference.md). +For larger or more-complex diagrams, you can alternatively apply the ELK (Eclipse Layout Kernel) layout using your YAML frontmatter's `config`. For more information, see [Customizing ELK Layout](../intro/syntax-reference.md#customizing-elk-layout). -``` +```yaml --- config: - layout: elk + layout: elk --- ``` Your Mermaid code should be similar to the following: -``````mermaid-example -```mermaid +```mermaid-example --- title: Order example config: @@ -434,7 +433,6 @@ erDiagram ORDER ||--|{ LINE-ITEM : contains CUSTOMER }|..|{ DELIVERY-ADDRESS : uses ``` -`````` ```note Note that the site needs to use mermaid version 9.4+ for this to work and have this featured enabled in the lazy-loading configuration. From 92c0aa433101b8ce7477690a8a4062e55c2547e4 Mon Sep 17 00:00:00 2001 From: Alois Klink Date: Mon, 7 Apr 2025 17:41:14 +0800 Subject: [PATCH 38/50] build(esbuild): support multiple IIFE packages Support multiple IIFE packages by namespacing all of them into a `globalThis.__esbuild_esm_mermaid_nm` object. --- .esbuild/util.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.esbuild/util.ts b/.esbuild/util.ts index 6d6d1d59b..dde0352af 100644 --- a/.esbuild/util.ts +++ b/.esbuild/util.ts @@ -58,6 +58,7 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { format, minify, options: { name, file, packageName }, + globalName = 'mermaid', } = options; const external: string[] = ['require', 'fs', 'path']; const outFileName = getFileName(name, options); @@ -68,6 +69,7 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { }, metafile, minify, + globalName, logLevel: 'info', chunkNames: `chunks/${outFileName}/[name]-[hash]`, define: { @@ -89,11 +91,12 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { if (format === 'iife') { output.format = 'iife'; output.splitting = false; - output.globalName = '__esbuild_esm_mermaid'; + const originalGlobalName = output.globalName ?? 'mermaid'; + output.globalName = `__esbuild_esm_mermaid_nm[${JSON.stringify(originalGlobalName)}]`; // Workaround for removing the .default access in esbuild IIFE. // https://github.com/mermaid-js/mermaid/pull/4109#discussion_r1292317396 output.footer = { - js: 'globalThis.mermaid = globalThis.__esbuild_esm_mermaid.default;', + js: `globalThis[${JSON.stringify(originalGlobalName)}] = globalThis.${output.globalName}.default;`, }; output.outExtension = { '.js': '.js' }; } else { From 535121125663accd83e5e8b9d5a3e73b5ea7ac84 Mon Sep 17 00:00:00 2001 From: Alois Klink Date: Mon, 7 Apr 2025 16:49:40 +0800 Subject: [PATCH 39/50] build(zenuml): add back IIFE ZenUML builds These are present in [v0.2.0][1] so removing these would be a breaking change. I suspect we accidentally removed them when we moved from Vite to ESBuild. [1]: https://www.npmjs.com/package/@mermaid-js/mermaid-zenuml/v/0.2.0 --- .esbuild/build.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.esbuild/build.ts b/.esbuild/build.ts index 423e8f047..05002cb16 100644 --- a/.esbuild/build.ts +++ b/.esbuild/build.ts @@ -34,6 +34,19 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => { { ...iifeOptions, minify: true, metafile: shouldVisualize } ); } + if (entryName === 'mermaid-zenuml') { + const iifeOptions: MermaidBuildOptions = { + ...commonOptions, + format: 'iife', + globalName: 'mermaid-zenuml', + }; + buildConfigs.push( + // mermaid-zenuml.js + { ...iifeOptions }, + // mermaid-zenuml.min.js + { ...iifeOptions, minify: true, metafile: shouldVisualize } + ); + } const results = await Promise.all(buildConfigs.map((option) => build(getBuildConfig(option)))); From 03119fea2c6f88927676d25d4d09a808b1a1807a Mon Sep 17 00:00:00 2001 From: Alois Klink Date: Mon, 7 Apr 2025 17:02:30 +0800 Subject: [PATCH 40/50] chore(zenuml): add pending ZenUML changesets Add ZenUML changesets for: - Bumping the minimum version of ZenUML to 3.23.28 - Limiting the `peerDepdencies` to v10 and v11 See: 9d06d8f31e7f12af9e9e092214f907f2dc93ad75 See: 0ad44c12feead9d20c6a870a49327ada58d6e657 --- .changeset/honest-trees-dress.md | 7 +++++++ .changeset/yellow-mirrors-change.md | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 .changeset/honest-trees-dress.md create mode 100644 .changeset/yellow-mirrors-change.md diff --git a/.changeset/honest-trees-dress.md b/.changeset/honest-trees-dress.md new file mode 100644 index 000000000..054f1bedb --- /dev/null +++ b/.changeset/honest-trees-dress.md @@ -0,0 +1,7 @@ +--- +'@mermaid-js/mermaid-zenuml': patch +--- + +chore: bump minimum ZenUML version to 3.23.28 + +commit: 9d06d8f31e7f12af9e9e092214f907f2dc93ad75 diff --git a/.changeset/yellow-mirrors-change.md b/.changeset/yellow-mirrors-change.md new file mode 100644 index 000000000..09a766104 --- /dev/null +++ b/.changeset/yellow-mirrors-change.md @@ -0,0 +1,7 @@ +--- +'@mermaid-js/mermaid-zenuml': patch +--- + +fix(zenuml): limit `peerDependencies` to Mermaid v10 and v11 + +commit: 0ad44c12feead9d20c6a870a49327ada58d6e657 From 5a6831ae7e3a5ee729171bf9f682c02dbdebcc6f Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Tue, 8 Apr 2025 10:13:59 +0530 Subject: [PATCH 41/50] chore: Fix branch in e2e-timings --- .github/workflows/e2e-timings.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/e2e-timings.yml b/.github/workflows/e2e-timings.yml index b51557b69..1796a0608 100644 --- a/.github/workflows/e2e-timings.yml +++ b/.github/workflows/e2e-timings.yml @@ -51,8 +51,9 @@ jobs: author_name: 'github-actions[bot]' author_email: '41898282+github-actions[bot]@users.noreply.github.com' message: 'chore: update E2E timings' + new_branch: update-timings - name: Create Pull Request uses: peter-evans/create-pull-request@v5 with: - branch: release-promotion + branch: update-timings title: Update E2E Timings From 404216273a90cf3bb298e063821332cfb0f17cde Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Tue, 8 Apr 2025 11:01:28 +0530 Subject: [PATCH 42/50] chore: Fix PR action in e2e-timings --- .github/workflows/e2e-timings.yml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/e2e-timings.yml b/.github/workflows/e2e-timings.yml index 1796a0608..6b681bbd8 100644 --- a/.github/workflows/e2e-timings.yml +++ b/.github/workflows/e2e-timings.yml @@ -44,16 +44,13 @@ jobs: SPLIT: 1 SPLIT_INDEX: 0 SPLIT_FILE: 'cypress/timings.json' - - name: Commit changes - uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 - with: - add: 'cypress/timings.json' - author_name: 'github-actions[bot]' - author_email: '41898282+github-actions[bot]@users.noreply.github.com' - message: 'chore: update E2E timings' - new_branch: update-timings - - name: Create Pull Request - uses: peter-evans/create-pull-request@v5 + - name: Commit and create pull request + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e with: + add-paths: | + cypress/timings.json + commit-message: 'chore: update E2E timings' branch: update-timings title: Update E2E Timings + delete-branch: true + sign-commits: true From 44e668e704e87cfc7886b6dfd90126869616d932 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Tue, 8 Apr 2025 11:58:46 +0530 Subject: [PATCH 43/50] chore: Update permission for timings action --- .github/workflows/e2e-timings.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/e2e-timings.yml b/.github/workflows/e2e-timings.yml index 6b681bbd8..4c36bc238 100644 --- a/.github/workflows/e2e-timings.yml +++ b/.github/workflows/e2e-timings.yml @@ -11,6 +11,7 @@ concurrency: ${{ github.workflow }}-${{ github.ref }} permissions: contents: write + pull-requests: write jobs: timings: From 926862c196b9974e996c5c6da2a8f7e878da58d9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 06:53:44 +0000 Subject: [PATCH 44/50] chore: update E2E timings --- cypress/timings.json | 134 +++++++++++++++++++++++++++++++------------ 1 file changed, 97 insertions(+), 37 deletions(-) diff --git a/cypress/timings.json b/cypress/timings.json index 3455d82fc..6164a81fb 100644 --- a/cypress/timings.json +++ b/cypress/timings.json @@ -2,151 +2,211 @@ "durations": [ { "spec": "cypress/integration/other/configuration.spec.js", - "duration": 4989 + "duration": 5475 }, { "spec": "cypress/integration/other/external-diagrams.spec.js", - "duration": 1382 + "duration": 2037 }, { "spec": "cypress/integration/other/ghsa.spec.js", - "duration": 3178 + "duration": 3207 }, { "spec": "cypress/integration/other/iife.spec.js", - "duration": 1372 + "duration": 1915 }, { "spec": "cypress/integration/other/interaction.spec.js", - "duration": 8998 + "duration": 10952 }, { "spec": "cypress/integration/other/rerender.spec.js", - "duration": 1249 + "duration": 1872 }, { "spec": "cypress/integration/other/xss.spec.js", - "duration": 25664 + "duration": 26686 }, { "spec": "cypress/integration/rendering/appli.spec.js", - "duration": 1928 + "duration": 2629 }, { "spec": "cypress/integration/rendering/architecture.spec.ts", - "duration": 2330 + "duration": 104 }, { "spec": "cypress/integration/rendering/block.spec.js", - "duration": 11156 + "duration": 14765 }, { "spec": "cypress/integration/rendering/c4.spec.js", - "duration": 3418 + "duration": 4913 + }, + { + "spec": "cypress/integration/rendering/classDiagram-elk-v3.spec.js", + "duration": 36667 + }, + { + "spec": "cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js", + "duration": 33813 }, { "spec": "cypress/integration/rendering/classDiagram-v2.spec.js", - "duration": 14866 + "duration": 20441 + }, + { + "spec": "cypress/integration/rendering/classDiagram-v3.spec.js", + "duration": 32504 }, { "spec": "cypress/integration/rendering/classDiagram.spec.js", - "duration": 9894 + "duration": 13772 }, { "spec": "cypress/integration/rendering/conf-and-directives.spec.js", - "duration": 5778 + "duration": 7978 }, { "spec": "cypress/integration/rendering/current.spec.js", - "duration": 1690 + "duration": 2101 + }, + { + "spec": "cypress/integration/rendering/erDiagram-unified.spec.js", + "duration": 76556 }, { "spec": "cypress/integration/rendering/erDiagram.spec.js", - "duration": 9144 + "duration": 12756 }, { "spec": "cypress/integration/rendering/errorDiagram.spec.js", - "duration": 1951 + "duration": 2766 }, { "spec": "cypress/integration/rendering/flowchart-elk.spec.js", - "duration": 2196 + "duration": 35641 }, { "spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js", - "duration": 21029 + "duration": 26915 }, { "spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts", - "duration": 16087 + "duration": 21171 }, { "spec": "cypress/integration/rendering/flowchart-v2.spec.js", - "duration": 27465 + "duration": 37844 }, { "spec": "cypress/integration/rendering/flowchart.spec.js", - "duration": 20035 + "duration": 26254 }, { "spec": "cypress/integration/rendering/gantt.spec.js", - "duration": 11366 + "duration": 15149 }, { "spec": "cypress/integration/rendering/gitGraph.spec.js", - "duration": 34025 + "duration": 45049 }, { "spec": "cypress/integration/rendering/iconShape.spec.ts", - "duration": 185902 + "duration": 250225 }, { "spec": "cypress/integration/rendering/imageShape.spec.ts", - "duration": 41631 + "duration": 51531 }, { "spec": "cypress/integration/rendering/info.spec.ts", - "duration": 1736 + "duration": 2455 }, { "spec": "cypress/integration/rendering/journey.spec.js", - "duration": 2247 + "duration": 3181 + }, + { + "spec": "cypress/integration/rendering/kanban.spec.ts", + "duration": 6298 }, { "spec": "cypress/integration/rendering/katex.spec.js", - "duration": 2144 + "duration": 3065 }, { "spec": "cypress/integration/rendering/marker_unique_id.spec.js", - "duration": 1646 + "duration": 2521 }, { "spec": "cypress/integration/rendering/mindmap.spec.ts", - "duration": 6406 + "duration": 9341 }, { "spec": "cypress/integration/rendering/newShapes.spec.ts", - "duration": 107219 + "duration": 132809 + }, + { + "spec": "cypress/integration/rendering/oldShapes.spec.ts", + "duration": 101299 + }, + { + "spec": "cypress/integration/rendering/packet.spec.ts", + "duration": 3481 + }, + { + "spec": "cypress/integration/rendering/pie.spec.ts", + "duration": 4878 + }, + { + "spec": "cypress/integration/rendering/quadrantChart.spec.js", + "duration": 7416 + }, + { + "spec": "cypress/integration/rendering/radar.spec.js", + "duration": 4554 + }, + { + "spec": "cypress/integration/rendering/requirement.spec.js", + "duration": 2068 + }, + { + "spec": "cypress/integration/rendering/requirementDiagram-unified.spec.js", + "duration": 47583 + }, + { + "spec": "cypress/integration/rendering/sankey.spec.ts", + "duration": 5792 + }, + { + "spec": "cypress/integration/rendering/sequencediagram.spec.js", + "duration": 33035 + }, + { + "spec": "cypress/integration/rendering/stateDiagram-v2.spec.js", + "duration": 22716 }, { "spec": "cypress/integration/rendering/stateDiagram.spec.js", - "duration": 15834 + "duration": 13868 }, { "spec": "cypress/integration/rendering/theme.spec.js", - "duration": 33240 + "duration": 26376 }, { "spec": "cypress/integration/rendering/timeline.spec.ts", - "duration": 7122 + "duration": 5872 }, { "spec": "cypress/integration/rendering/xyChart.spec.js", - "duration": 11127 + "duration": 9469 }, { "spec": "cypress/integration/rendering/zenuml.spec.js", - "duration": 2391 + "duration": 2742 } ] } From 2b05d7e1edef635e6c80cb383b10ea0a89279f41 Mon Sep 17 00:00:00 2001 From: Aaron Moat <2937187+AaronMoat@users.noreply.github.com> Date: Tue, 8 Apr 2025 19:49:47 +1000 Subject: [PATCH 45/50] Fix incorrect `style="undefined;"` output in some Mermaid diagrams --- .changeset/gold-shoes-camp.md | 5 +++++ .../mermaid/src/rendering-util/rendering-elements/edges.js | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/gold-shoes-camp.md diff --git a/.changeset/gold-shoes-camp.md b/.changeset/gold-shoes-camp.md new file mode 100644 index 000000000..77ff7309b --- /dev/null +++ b/.changeset/gold-shoes-camp.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +Fix incorrect `style="undefined;"` output in some Mermaid diagrams diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index 434c53856..ce4244ff2 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -562,7 +562,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod } let svgPath; let linePath = lineFunction(lineData); - const edgeStyles = Array.isArray(edge.style) ? edge.style : [edge.style]; + const edgeStyles = Array.isArray(edge.style) ? edge.style : edge.style ? [edge.style] : []; let strokeColor = edgeStyles.find((style) => style?.startsWith('stroke:')); if (edge.look === 'handDrawn') { From d25770ee738fc9704bae37ca09ebc8d4fbd1b65c Mon Sep 17 00:00:00 2001 From: Aaron Moat <2937187+AaronMoat@users.noreply.github.com> Date: Tue, 8 Apr 2025 19:55:05 +1000 Subject: [PATCH 46/50] Format changeset message --- .changeset/gold-shoes-camp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/gold-shoes-camp.md b/.changeset/gold-shoes-camp.md index 77ff7309b..3018e7381 100644 --- a/.changeset/gold-shoes-camp.md +++ b/.changeset/gold-shoes-camp.md @@ -2,4 +2,4 @@ 'mermaid': patch --- -Fix incorrect `style="undefined;"` output in some Mermaid diagrams +fix: Remove incorrect `style="undefined;"` attributes in some Mermaid diagrams From 7a5f999f42b28ce0d9ec77b9ad2752720e9eec4b Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Wed, 9 Apr 2025 12:08:57 +0530 Subject: [PATCH 47/50] chore: Add compare-timings script Avoid creating unnecessary PRs when there is no significant timings change. --- .github/workflows/e2e-timings.yml | 8 +++ scripts/compare-timings.ts | 88 +++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 scripts/compare-timings.ts diff --git a/.github/workflows/e2e-timings.yml b/.github/workflows/e2e-timings.yml index 4c36bc238..85778f421 100644 --- a/.github/workflows/e2e-timings.yml +++ b/.github/workflows/e2e-timings.yml @@ -30,6 +30,10 @@ jobs: uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 with: runTests: false + + - name: Copy previous timings + run: cp cypress/timings.json cypress/timings-old.json + - name: Cypress run uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 id: cypress @@ -45,6 +49,10 @@ jobs: SPLIT: 1 SPLIT_INDEX: 0 SPLIT_FILE: 'cypress/timings.json' + + - name: Compare timings + run: pnpm tsx scripts/compare-timings.ts + - name: Commit and create pull request uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e with: diff --git a/scripts/compare-timings.ts b/scripts/compare-timings.ts new file mode 100644 index 000000000..6c63190ad --- /dev/null +++ b/scripts/compare-timings.ts @@ -0,0 +1,88 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +interface Timing { + spec: string; + duration: number; +} + +interface TimingsFile { + durations: Timing[]; +} + +const TIMINGS_PATH = path.join(process.cwd(), 'cypress', 'timings.json'); +const TIMINGS_OLD_PATH = path.join(process.cwd(), 'cypress', 'timings-old.json'); + +function log(message: string): void { + // eslint-disable-next-line no-console + console.log(message); +} + +function readTimings(filePath: string): TimingsFile { + return JSON.parse(fs.readFileSync(filePath, 'utf8')); +} + +interface CleanupOptions { + keepNew: boolean; + reason: string; +} + +function cleanupFiles({ keepNew, reason }: CleanupOptions): void { + if (keepNew) { + log(`Keeping new timings: ${reason}`); + fs.unlinkSync(TIMINGS_OLD_PATH); + } else { + log(`Reverting to old timings: ${reason}`); + fs.unlinkSync(TIMINGS_PATH); + fs.renameSync(TIMINGS_OLD_PATH, TIMINGS_PATH); + } +} + +function compareTimings(): void { + const oldTimings = readTimings(TIMINGS_OLD_PATH); + const newTimings = readTimings(TIMINGS_PATH); + + const oldSpecs = new Set(oldTimings.durations.map((d) => d.spec)); + const newSpecs = new Set(newTimings.durations.map((d) => d.spec)); + + // Check if specs were added or removed + const addedSpecs = [...newSpecs].filter((spec) => !oldSpecs.has(spec)); + const removedSpecs = [...oldSpecs].filter((spec) => !newSpecs.has(spec)); + + if (addedSpecs.length > 0 || removedSpecs.length > 0) { + log('Specs changed:'); + if (addedSpecs.length > 0) { + log(`Added: ${addedSpecs.join(', ')}`); + } + if (removedSpecs.length > 0) { + log(`Removed: ${removedSpecs.join(', ')}`); + } + return cleanupFiles({ keepNew: true, reason: 'Specs were added or removed' }); + } + + // Check timing variations + const timingChanges = newTimings.durations.map((newTiming) => { + const oldTiming = oldTimings.durations.find((d) => d.spec === newTiming.spec); + if (!oldTiming) { + throw new Error(`Could not find old timing for spec: ${newTiming.spec}`); + } + const change = Math.abs(newTiming.duration - oldTiming.duration) / oldTiming.duration; + return { spec: newTiming.spec, change }; + }); + + const significantChanges = timingChanges.filter((t) => t.change >= 0.2); + + if (significantChanges.length === 0) { + log('No significant timing changes detected (threshold: 20%)'); + return cleanupFiles({ keepNew: false, reason: 'No significant timing changes' }); + } + + log('Significant timing changes:'); + significantChanges.forEach((t) => { + log(`${t.spec}: ${(t.change * 100).toFixed(1)}%`); + }); + + cleanupFiles({ keepNew: true, reason: 'Significant timing changes detected' }); +} + +compareTimings(); From 97e35fd30a6fac8029ceb31ccdd1452a21fde006 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Wed, 9 Apr 2025 12:19:13 +0530 Subject: [PATCH 48/50] chore: Use git to read old timings --- .github/workflows/e2e-timings.yml | 3 -- scripts/compare-timings.ts | 49 +++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/.github/workflows/e2e-timings.yml b/.github/workflows/e2e-timings.yml index 85778f421..af2c58955 100644 --- a/.github/workflows/e2e-timings.yml +++ b/.github/workflows/e2e-timings.yml @@ -31,9 +31,6 @@ jobs: with: runTests: false - - name: Copy previous timings - run: cp cypress/timings.json cypress/timings-old.json - - name: Cypress run uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 id: cypress diff --git a/scripts/compare-timings.ts b/scripts/compare-timings.ts index 6c63190ad..aaf070767 100644 --- a/scripts/compare-timings.ts +++ b/scripts/compare-timings.ts @@ -1,5 +1,22 @@ +/** + * Compares new E2E test timings with previous timings and determines whether to keep the new timings. + * + * The script will: + * 1. Read old timings from git HEAD + * 2. Read new timings from the current file + * 3. Compare the timings and specs + * 4. Keep new timings if: + * - Specs were added/removed + * - Any timing changed by 20% or more + * 5. Revert to old timings if: + * - No significant timing changes + * + * This helps prevent unnecessary timing updates when test performance hasn't changed significantly. + */ + import fs from 'node:fs'; import path from 'node:path'; +import { execSync } from 'node:child_process'; interface Timing { spec: string; @@ -10,37 +27,45 @@ interface TimingsFile { durations: Timing[]; } -const TIMINGS_PATH = path.join(process.cwd(), 'cypress', 'timings.json'); -const TIMINGS_OLD_PATH = path.join(process.cwd(), 'cypress', 'timings-old.json'); +interface CleanupOptions { + keepNew: boolean; + reason: string; +} + +const TIMINGS_FILE = 'cypress/timings.json'; +const TIMINGS_PATH = path.join(process.cwd(), TIMINGS_FILE); function log(message: string): void { // eslint-disable-next-line no-console console.log(message); } -function readTimings(filePath: string): TimingsFile { - return JSON.parse(fs.readFileSync(filePath, 'utf8')); +function readOldTimings(): TimingsFile { + try { + const oldContent = execSync(`git show HEAD:${TIMINGS_FILE}`, { encoding: 'utf8' }); + return JSON.parse(oldContent); + } catch { + log('Error getting old timings, using empty file'); + return { durations: [] }; + } } -interface CleanupOptions { - keepNew: boolean; - reason: string; +function readNewTimings(): TimingsFile { + return JSON.parse(fs.readFileSync(TIMINGS_PATH, 'utf8')); } function cleanupFiles({ keepNew, reason }: CleanupOptions): void { if (keepNew) { log(`Keeping new timings: ${reason}`); - fs.unlinkSync(TIMINGS_OLD_PATH); } else { log(`Reverting to old timings: ${reason}`); - fs.unlinkSync(TIMINGS_PATH); - fs.renameSync(TIMINGS_OLD_PATH, TIMINGS_PATH); + execSync(`git checkout HEAD -- ${TIMINGS_FILE}`); } } function compareTimings(): void { - const oldTimings = readTimings(TIMINGS_OLD_PATH); - const newTimings = readTimings(TIMINGS_PATH); + const oldTimings = readOldTimings(); + const newTimings = readNewTimings(); const oldSpecs = new Set(oldTimings.durations.map((d) => d.spec)); const newSpecs = new Set(newTimings.durations.map((d) => d.spec)); From f87d0dd88ae4db3231ce1a4dfe20b2d07389a938 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Wed, 9 Apr 2025 13:20:19 +0530 Subject: [PATCH 49/50] chore: Update change detection logic --- scripts/compare-timings.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scripts/compare-timings.ts b/scripts/compare-timings.ts index aaf070767..1dbfc41d0 100644 --- a/scripts/compare-timings.ts +++ b/scripts/compare-timings.ts @@ -91,20 +91,22 @@ function compareTimings(): void { if (!oldTiming) { throw new Error(`Could not find old timing for spec: ${newTiming.spec}`); } - const change = Math.abs(newTiming.duration - oldTiming.duration) / oldTiming.duration; - return { spec: newTiming.spec, change }; + const change = Math.abs(newTiming.duration - oldTiming.duration); + const changePercent = change / oldTiming.duration; + return { spec: newTiming.spec, change, changePercent }; }); - const significantChanges = timingChanges.filter((t) => t.change >= 0.2); + // Filter changes that's more than 5 seconds and 20% different + const significantChanges = timingChanges.filter((t) => t.change > 5000 && t.changePercent >= 0.2); if (significantChanges.length === 0) { - log('No significant timing changes detected (threshold: 20%)'); + log('No significant timing changes detected (threshold: 5s and 20%)'); return cleanupFiles({ keepNew: false, reason: 'No significant timing changes' }); } log('Significant timing changes:'); significantChanges.forEach((t) => { - log(`${t.spec}: ${(t.change * 100).toFixed(1)}%`); + log(`${t.spec}: ${t.change.toFixed(1)}ms (${(t.changePercent * 100).toFixed(1)}%)`); }); cleanupFiles({ keepNew: true, reason: 'Significant timing changes detected' }); From ea987861f3a733331ffa139cebf4b0ca6386481f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 9 Apr 2025 13:45:21 +0000 Subject: [PATCH 50/50] chore(deps): update eslint --- package.json | 16 +- pnpm-lock.yaml | 975 +++++++++++++++++++------------------------------ 2 files changed, 383 insertions(+), 608 deletions(-) diff --git a/package.json b/package.json index c2901ca06..df7e36ade 100644 --- a/package.json +++ b/package.json @@ -67,9 +67,9 @@ "@argos-ci/cypress": "^3.2.0", "@changesets/changelog-github": "^0.5.1", "@changesets/cli": "^2.27.12", - "@cspell/eslint-plugin": "^8.8.4", + "@cspell/eslint-plugin": "^8.18.1", "@cypress/code-coverage": "^3.12.49", - "@eslint/js": "^9.4.0", + "@eslint/js": "^9.24.0", "@rollup/plugin-typescript": "^12.1.2", "@types/cors": "^2.8.17", "@types/express": "^5.0.0", @@ -93,12 +93,12 @@ "cypress-image-snapshot": "^4.0.1", "cypress-split": "^1.24.14", "esbuild": "^0.25.0", - "eslint": "^9.20.1", - "eslint-config-prettier": "^10.0.0", - "eslint-plugin-cypress": "^4.1.0", + "eslint": "^9.24.0", + "eslint-config-prettier": "^10.1.1", + "eslint-plugin-cypress": "^4.2.1", "eslint-plugin-html": "^8.1.2", - "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^50.0.1", + "eslint-plugin-jest": "^28.11.0", + "eslint-plugin-jsdoc": "^50.6.9", "eslint-plugin-json": "^4.0.1", "eslint-plugin-lodash": "^8.0.0", "eslint-plugin-markdown": "^5.1.0", @@ -126,7 +126,7 @@ "tslib": "^2.8.1", "tsx": "^4.7.3", "typescript": "~5.7.3", - "typescript-eslint": "^8.24.1", + "typescript-eslint": "^8.29.1", "vite": "^6.1.1", "vite-plugin-istanbul": "^7.0.0", "vitest": "^3.0.6" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7290deed8..00ef70dfd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,14 +26,14 @@ importers: specifier: ^2.27.12 version: 2.28.1 '@cspell/eslint-plugin': - specifier: ^8.8.4 - version: 8.14.4(eslint@9.20.1(jiti@2.4.2)) + specifier: ^8.18.1 + version: 8.18.1(eslint@9.24.0(jiti@2.4.2)) '@cypress/code-coverage': specifier: ^3.12.49 version: 3.13.4(@babel/core@7.26.9)(@babel/preset-env@7.26.9(@babel/core@7.26.9))(babel-loader@9.2.1(@babel/core@7.26.9)(webpack@5.95.0(esbuild@0.25.0)))(cypress@14.0.3)(webpack@5.95.0(esbuild@0.25.0)) '@eslint/js': - specifier: ^9.4.0 - version: 9.12.0 + specifier: ^9.24.0 + version: 9.24.0 '@rollup/plugin-typescript': specifier: ^12.1.2 version: 12.1.2(rollup@4.34.8)(tslib@2.8.1)(typescript@5.7.3) @@ -104,32 +104,32 @@ importers: specifier: ^0.25.0 version: 0.25.0 eslint: - specifier: ^9.20.1 - version: 9.20.1(jiti@2.4.2) + specifier: ^9.24.0 + version: 9.24.0(jiti@2.4.2) eslint-config-prettier: - specifier: ^10.0.0 - version: 10.0.1(eslint@9.20.1(jiti@2.4.2)) + specifier: ^10.1.1 + version: 10.1.1(eslint@9.24.0(jiti@2.4.2)) eslint-plugin-cypress: - specifier: ^4.1.0 - version: 4.1.0(eslint@9.20.1(jiti@2.4.2)) + specifier: ^4.2.1 + version: 4.2.1(eslint@9.24.0(jiti@2.4.2)) eslint-plugin-html: specifier: ^8.1.2 version: 8.1.2 eslint-plugin-jest: - specifier: ^28.6.0 - version: 28.8.3(@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.5))(typescript@5.7.3) + specifier: ^28.11.0 + version: 28.11.0(@typescript-eslint/eslint-plugin@8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.5))(typescript@5.7.3) eslint-plugin-jsdoc: - specifier: ^50.0.1 - version: 50.3.2(eslint@9.20.1(jiti@2.4.2)) + specifier: ^50.6.9 + version: 50.6.9(eslint@9.24.0(jiti@2.4.2)) eslint-plugin-json: specifier: ^4.0.1 version: 4.0.1 eslint-plugin-lodash: specifier: ^8.0.0 - version: 8.0.0(eslint@9.20.1(jiti@2.4.2)) + version: 8.0.0(eslint@9.24.0(jiti@2.4.2)) eslint-plugin-markdown: specifier: ^5.1.0 - version: 5.1.0(eslint@9.20.1(jiti@2.4.2)) + version: 5.1.0(eslint@9.24.0(jiti@2.4.2)) eslint-plugin-no-only-tests: specifier: ^3.3.0 version: 3.3.0 @@ -138,7 +138,7 @@ importers: version: 0.4.0 eslint-plugin-unicorn: specifier: ^58.0.0 - version: 58.0.0(eslint@9.20.1(jiti@2.4.2)) + version: 58.0.0(eslint@9.24.0(jiti@2.4.2)) express: specifier: ^4.19.2 version: 4.21.0 @@ -203,8 +203,8 @@ importers: specifier: ~5.7.3 version: 5.7.3 typescript-eslint: - specifier: ^8.24.1 - version: 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + specifier: ^8.29.1 + version: 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) vite: specifier: ^6.1.1 version: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0) @@ -1463,52 +1463,49 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} - '@cspell/cspell-bundled-dicts@8.14.4': - resolution: {integrity: sha512-JHZOpCJzN6fPBapBOvoeMxZbr0ZA11ZAkwcqM4w0lKoacbi6TwK8GIYf66hHvwLmMeav75TNXWE6aPTvBLMMqA==} - engines: {node: '>=18'} - '@cspell/cspell-bundled-dicts@8.17.4': resolution: {integrity: sha512-oPNQU3Uwc0OnvAmC8Vs7DSCRBhGRbZvO8J57JEnJ6YMNyCJZpKq050OzbAWmNdjjZ7yRLJ+LOcxhzdFg2Qn4Yw==} engines: {node: '>=18'} + '@cspell/cspell-bundled-dicts@8.18.1': + resolution: {integrity: sha512-gxciVVfQqCVXYH0p2Q5D7x7/SgaW3Wv5UjRwO+TCme0P2lVLl/IcfjkujZX+6UQkT7X4QRglXo1QN141UcCRCQ==} + engines: {node: '>=18'} + '@cspell/cspell-json-reporter@8.17.4': resolution: {integrity: sha512-O7V2hMt6zPt2Eu5LSxFyD/dcZRUOASeY+8oE1O2xanfJUMOG1EldCt8LERSmU829RQ4VF4H2Z9TbeQzx+4G21w==} engines: {node: '>=18'} - '@cspell/cspell-pipe@8.14.4': - resolution: {integrity: sha512-CLLdouqfrQ4rqdQdPu0Oo+HHCU/oLYoEsK1nNPb28cZTFxnn0cuSPKB6AMPBJmMwdfJ6fMD0BCKNbEe1UNLHcw==} - engines: {node: '>=18'} - '@cspell/cspell-pipe@8.17.4': resolution: {integrity: sha512-0KzqYetKMT9c3Pt77yRla2/zLDitpztEQ/VPYAbW5DCW+btRe5pAb6VQ7U6HKA2HoM2rhlLTWOBh4jauRFtgxA==} engines: {node: '>=18'} - '@cspell/cspell-resolver@8.14.4': - resolution: {integrity: sha512-s3uZyymJ04yn8+zlTp7Pt1WRSlAel6XVo+iZRxls3LSvIP819KK64DoyjCD2Uon0Vg9P/K7aAPt8GcxDcnJtgA==} + '@cspell/cspell-pipe@8.18.1': + resolution: {integrity: sha512-QHndTQPkR1c02pvvQ7UKFtLjCXgY0OcX8zjTLrCkynmcQxJFjAZAh9cJ7NMOAxab+ciSnkaVf4KWaRSEG17z8Q==} engines: {node: '>=18'} '@cspell/cspell-resolver@8.17.4': resolution: {integrity: sha512-1Z3yZRuhnyGCheD2nt/ZswV+ulXBOfnKCoyfkUKNAR5ALkrqv6bjXXwZrpEi2cIK1km4/59ybT72+r2Ry9dGUw==} engines: {node: '>=18'} - '@cspell/cspell-service-bus@8.14.4': - resolution: {integrity: sha512-i3UG+ep63akNsDXZrtGgICNF3MLBHtvKe/VOIH6+L+NYaAaVHqqQvOY9MdUwt1HXh8ElzfwfoRp36wc5aAvt6g==} + '@cspell/cspell-resolver@8.18.1': + resolution: {integrity: sha512-T2sUBv0p9Hnfyg1xT1u3ESKuIWaaIDo0I8idh5DSlTpHgLjdIeAwasmFjEJ28qZv8OKSGawcSQKgJbStfbZASQ==} engines: {node: '>=18'} '@cspell/cspell-service-bus@8.17.4': resolution: {integrity: sha512-S8fENifriBW8KdDIvOnsP9gdEyCp1zrs4GT15vmDvm6uoevj2mfmdCj4/EbM1KbmmNAh1tlidAgn2OWdtyW7Lg==} engines: {node: '>=18'} - '@cspell/cspell-types@8.14.4': - resolution: {integrity: sha512-VXwikqdHgjOVperVVCn2DOe8W3rPIswwZtMHfRYnagpzZo/TOntIjkXPJSfTtl/cFyx5DnCBsDH8ytKGlMeHkw==} + '@cspell/cspell-service-bus@8.18.1': + resolution: {integrity: sha512-PwWl7EyhGIu4wHEhvBJb6xVlqMtFwQk0qLDArBvugL6nA+MX9NfG/w7PTgS7tCkFjVF1ku2sDzDLTDWwEk+MLw==} engines: {node: '>=18'} '@cspell/cspell-types@8.17.4': resolution: {integrity: sha512-1K6tXEMXSaoUXhH3TiaCyh3Nh8ZE0wPej0+wa5HAMtdcY1B3FGvHZ9DltkgZxbzs3bGNXIySFE5ITqULbhweBA==} engines: {node: '>=18'} - '@cspell/dict-ada@4.0.2': - resolution: {integrity: sha512-0kENOWQeHjUlfyId/aCM/mKXtkEgV0Zu2RhUXCBr4hHo9F9vph+Uu8Ww2b0i5a4ZixoIkudGA+eJvyxrG1jUpA==} + '@cspell/cspell-types@8.18.1': + resolution: {integrity: sha512-d/nMG+qnMbI/1JPm+lD0KcKpgtEHMRsHxkdtGyNCDgvHL/JOGaSHc5ERS3IUgBW0Dfya/3z9wPdaMcHEzt7YCQ==} + engines: {node: '>=18'} '@cspell/dict-ada@4.1.0': resolution: {integrity: sha512-7SvmhmX170gyPd+uHXrfmqJBY5qLcCX8kTGURPVeGxmt8XNXT75uu9rnZO+jwrfuU2EimNoArdVy5GZRGljGNg==} @@ -1516,62 +1513,38 @@ packages: '@cspell/dict-al@1.1.0': resolution: {integrity: sha512-PtNI1KLmYkELYltbzuoztBxfi11jcE9HXBHCpID2lou/J4VMYKJPNqe4ZjVzSI9NYbMnMnyG3gkbhIdx66VSXg==} - '@cspell/dict-aws@4.0.4': - resolution: {integrity: sha512-6AWI/Kkf+RcX/J81VX8+GKLeTgHWEr/OMhGk3dHQzWK66RaqDJCGDqi7494ghZKcBB7dGa3U5jcKw2FZHL/u3w==} - '@cspell/dict-aws@4.0.9': resolution: {integrity: sha512-bDYdnnJGwSkIZ4gzrauu7qzOs/ZAY/FnU4k11LgdMI8BhwMfsbsy2EI1iS+sD/BI5ZnNT9kU5YR3WADeNOmhRg==} - '@cspell/dict-bash@4.1.5': - resolution: {integrity: sha512-YGim/h7E2U5HCCb2ckNufT6/yyWygt9nSZ5C7qw6oOD3bygbObqD1+rlPor1JW+YyO+3GwTIHE70uKEEU6VZYw==} - '@cspell/dict-bash@4.2.0': resolution: {integrity: sha512-HOyOS+4AbCArZHs/wMxX/apRkjxg6NDWdt0jF9i9XkvJQUltMwEhyA2TWYjQ0kssBsnof+9amax2lhiZnh3kCg==} '@cspell/dict-companies@3.1.14': resolution: {integrity: sha512-iqo1Ce4L7h0l0GFSicm2wCLtfuymwkvgFGhmu9UHyuIcTbdFkDErH+m6lH3Ed+QuskJlpQ9dM7puMIGqUlVERw==} - '@cspell/dict-companies@3.1.4': - resolution: {integrity: sha512-y9e0amzEK36EiiKx3VAA+SHQJPpf2Qv5cCt5eTUSggpTkiFkCh6gRKQ97rVlrKh5GJrqinDwYIJtTsxuh2vy2Q==} - - '@cspell/dict-cpp@5.1.19': - resolution: {integrity: sha512-i/odUPNFLdqWisOktu6c4qjUR4k+P9Al2RCri3Wso9EFblp53xt/5jIUdGMdDDVQGqX7s/KLtdqNxNKqP3/d+w==} - '@cspell/dict-cpp@6.0.3': resolution: {integrity: sha512-OFrVXdxCeGKnon36Pe3yFjBuY4kzzEwWFf3vDz+cJTodZDkjFkBifQeTtt5YfimgF8cfAJZXkBCsxjipAgmAiw==} - '@cspell/dict-cryptocurrencies@5.0.0': - resolution: {integrity: sha512-Z4ARIw5+bvmShL+4ZrhDzGhnc9znaAGHOEMaB/GURdS/jdoreEDY34wdN0NtdLHDO5KO7GduZnZyqGdRoiSmYA==} + '@cspell/dict-cpp@6.0.7': + resolution: {integrity: sha512-mk0AUx6au1BJQBTT2Uq9L+y43E0Cy0Vcm6TrK3Toi2iuBLWOnDR/xRE4nZADBsi6WnWoiyl3/QqA1gW2zPkGvQ==} '@cspell/dict-cryptocurrencies@5.0.4': resolution: {integrity: sha512-6iFu7Abu+4Mgqq08YhTKHfH59mpMpGTwdzDB2Y8bbgiwnGFCeoiSkVkgLn1Kel2++hYcZ8vsAW/MJS9oXxuMag==} - '@cspell/dict-csharp@4.0.2': - resolution: {integrity: sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==} - '@cspell/dict-csharp@4.0.6': resolution: {integrity: sha512-w/+YsqOknjQXmIlWDRmkW+BHBPJZ/XDrfJhZRQnp0wzpPOGml7W0q1iae65P2AFRtTdPKYmvSz7AL5ZRkCnSIw==} - '@cspell/dict-css@4.0.13': - resolution: {integrity: sha512-WfOQkqlAJTo8eIQeztaH0N0P+iF5hsJVKFuhy4jmARPISy8Efcv8QXk2/IVbmjJH0/ZV7dKRdnY5JFVXuVz37g==} - '@cspell/dict-css@4.0.17': resolution: {integrity: sha512-2EisRLHk6X/PdicybwlajLGKF5aJf4xnX2uuG5lexuYKt05xV/J/OiBADmi8q9obhxf1nesrMQbqAt+6CsHo/w==} - '@cspell/dict-dart@2.2.1': - resolution: {integrity: sha512-yriKm7QkoPx3JPSSOcw6iX9gOb2N50bOo/wqWviqPYbhpMRh9Xiv6dkUy3+ot+21GuShZazO8X6U5+Vw67XEwg==} - '@cspell/dict-dart@2.3.0': resolution: {integrity: sha512-1aY90lAicek8vYczGPDKr70pQSTQHwMFLbmWKTAI6iavmb1fisJBS1oTmMOKE4ximDf86MvVN6Ucwx3u/8HqLg==} - '@cspell/dict-data-science@2.0.2': - resolution: {integrity: sha512-VwAck6OZQVqrscKyOrvllixIugIPF+Q6YoFNvXZCPhHGtNyOAVraD3S7kOgPYBdUjgno4QbdMWm92BUPqL1QjQ==} - '@cspell/dict-data-science@2.0.7': resolution: {integrity: sha512-XhAkK+nSW6zmrnWzusmZ1BpYLc62AWYHZc2p17u4nE2Z9XG5DleG55PCZxXQTKz90pmwlhFM9AfpkJsYaBWATA==} - '@cspell/dict-django@4.1.0': - resolution: {integrity: sha512-bKJ4gPyrf+1c78Z0Oc4trEB9MuhcB+Yg+uTTWsvhY6O2ncFYbB/LbEZfqhfmmuK/XJJixXfI1laF2zicyf+l0w==} + '@cspell/dict-data-science@2.0.8': + resolution: {integrity: sha512-uyAtT+32PfM29wRBeAkUSbkytqI8bNszNfAz2sGPtZBRmsZTYugKMEO9eDjAIE/pnT9CmbjNuoiXhk+Ss4fCOg==} '@cspell/dict-django@4.1.4': resolution: {integrity: sha512-fX38eUoPvytZ/2GA+g4bbdUtCMGNFSLbdJJPKX2vbewIQGfgSFJKY56vvcHJKAvw7FopjvgyS/98Ta9WN1gckg==} @@ -1579,23 +1552,14 @@ packages: '@cspell/dict-docker@1.1.12': resolution: {integrity: sha512-6d25ZPBnYZaT9D9An/x6g/4mk542R8bR3ipnby3QFCxnfdd6xaWiTcwDPsCgwN2aQZIQ1jX/fil9KmBEqIK/qA==} - '@cspell/dict-docker@1.1.7': - resolution: {integrity: sha512-XlXHAr822euV36GGsl2J1CkBIVg3fZ6879ZOg5dxTIssuhUOCiV2BuzKZmt6aIFmcdPmR14+9i9Xq+3zuxeX0A==} - - '@cspell/dict-dotnet@5.0.5': - resolution: {integrity: sha512-gjg0L97ee146wX47dnA698cHm85e7EOpf9mVrJD8DmEaqoo/k1oPy2g7c7LgKxK9XnqwoXxhLNnngPrwXOoEtQ==} - '@cspell/dict-dotnet@5.0.9': resolution: {integrity: sha512-JGD6RJW5sHtO5lfiJl11a5DpPN6eKSz5M1YBa1I76j4dDOIqgZB6rQexlDlK1DH9B06X4GdDQwdBfnpAB0r2uQ==} - '@cspell/dict-elixir@4.0.3': - resolution: {integrity: sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==} - '@cspell/dict-elixir@4.0.7': resolution: {integrity: sha512-MAUqlMw73mgtSdxvbAvyRlvc3bYnrDqXQrx5K9SwW8F7fRYf9V4vWYFULh+UWwwkqkhX9w03ZqFYRTdkFku6uA==} - '@cspell/dict-en-common-misspellings@2.0.4': - resolution: {integrity: sha512-lvOiRjV/FG4pAGZL3PN2GCVHSTCE92cwhfLGGkOsQtxSmef6WCHfHwp9auafkBlX0yFQSKDfq6/TlpQbjbJBtQ==} + '@cspell/dict-en-common-misspellings@2.0.10': + resolution: {integrity: sha512-80mXJLtr0tVEtzowrI7ycVae/ULAYImZUlr0kUTpa8i57AUk7Zy3pYBs44EYIKW7ZC9AHu4Qjjfq4vriAtyTDQ==} '@cspell/dict-en-common-misspellings@2.0.9': resolution: {integrity: sha512-O/jAr1VNtuyCFckbTmpeEf43ZFWVD9cJFvWaA6rO2IVmLirJViHWJUyBZOuQcesSplzEIw80MAYmnK06/MDWXQ==} @@ -1603,126 +1567,75 @@ packages: '@cspell/dict-en-gb@1.1.33': resolution: {integrity: sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==} - '@cspell/dict-en_us@4.3.23': - resolution: {integrity: sha512-l0SoEQBsi3zDSl3OuL4/apBkxjuj4hLIg/oy6+gZ7LWh03rKdF6VNtSZNXWAmMY+pmb1cGA3ouleTiJIglbsIg==} - '@cspell/dict-en_us@4.3.31': resolution: {integrity: sha512-MDc+1B0aFwQONS0JZ6w7ks2KFGkUcaNTFJ8kI6GHvFRmEl3zP5NJDwFEXFsoEdLDb86j2myauSWMJXR3JFuwbA==} + '@cspell/dict-en_us@4.4.0': + resolution: {integrity: sha512-TEfVT2NwvI9k1/ECjuC7GbULxenjJAbTLWMri1eMRk3mRGtqg5j0XzvvNRFuJWq8X48MdGVjsD+ZVI/VR94+eQ==} + '@cspell/dict-filetypes@3.0.11': resolution: {integrity: sha512-bBtCHZLo7MiSRUqx5KEiPdGOmXIlDGY+L7SJEtRWZENpAKE+96rT7hj+TUUYWBbCzheqHr0OXZJFEKDgsG/uZg==} - '@cspell/dict-filetypes@3.0.4': - resolution: {integrity: sha512-IBi8eIVdykoGgIv5wQhOURi5lmCNJq0we6DvqKoPQJHthXbgsuO1qrHSiUVydMiQl/XvcnUWTMeAlVUlUClnVg==} - - '@cspell/dict-flutter@1.0.0': - resolution: {integrity: sha512-W7k1VIc4KeV8BjEBxpA3cqpzbDWjfb7oXkEb0LecBCBp5Z7kcfnjT1YVotTx/U9PGyAOBhDaEdgZACVGNQhayw==} - '@cspell/dict-flutter@1.1.0': resolution: {integrity: sha512-3zDeS7zc2p8tr9YH9tfbOEYfopKY/srNsAa+kE3rfBTtQERAZeOhe5yxrnTPoufctXLyuUtcGMUTpxr3dO0iaA==} - '@cspell/dict-fonts@4.0.0': - resolution: {integrity: sha512-t9V4GeN/m517UZn63kZPUYP3OQg5f0OBLSd3Md5CU3eH1IFogSvTzHHnz4Wqqbv8NNRiBZ3HfdY/pqREZ6br3Q==} - '@cspell/dict-fonts@4.0.4': resolution: {integrity: sha512-cHFho4hjojBcHl6qxidl9CvUb492IuSk7xIf2G2wJzcHwGaCFa2o3gRcxmIg1j62guetAeDDFELizDaJlVRIOg==} - '@cspell/dict-fsharp@1.0.1': - resolution: {integrity: sha512-23xyPcD+j+NnqOjRHgW3IU7Li912SX9wmeefcY0QxukbAxJ/vAN4rBpjSwwYZeQPAn3fxdfdNZs03fg+UM+4yQ==} - '@cspell/dict-fsharp@1.1.0': resolution: {integrity: sha512-oguWmHhGzgbgbEIBKtgKPrFSVAFtvGHaQS0oj+vacZqMObwkapcTGu7iwf4V3Bc2T3caf0QE6f6rQfIJFIAVsw==} - '@cspell/dict-fullstack@3.2.0': - resolution: {integrity: sha512-sIGQwU6G3rLTo+nx0GKyirR5dQSFeTIzFTOrURw51ISf+jKG9a3OmvsVtc2OANfvEAOLOC9Wfd8WYhmsO8KRDQ==} - '@cspell/dict-fullstack@3.2.4': resolution: {integrity: sha512-JRRvaOLBZ13BO9sP395W+06tyO1Jy/87aFlKe9xQiCWMiwpCo2kGq0xBGq0PDWe253lYLs+GKrNmLU0fSxrObg==} - '@cspell/dict-gaming-terms@1.0.5': - resolution: {integrity: sha512-C3riccZDD3d9caJQQs1+MPfrUrQ+0KHdlj9iUR1QD92FgTOF6UxoBpvHUUZ9YSezslcmpFQK4xQQ5FUGS7uWfw==} + '@cspell/dict-fullstack@3.2.6': + resolution: {integrity: sha512-cSaq9rz5RIU9j+0jcF2vnKPTQjxGXclntmoNp4XB7yFX2621PxJcekGjwf/lN5heJwVxGLL9toR0CBlGKwQBgA==} '@cspell/dict-gaming-terms@1.1.0': resolution: {integrity: sha512-46AnDs9XkgJ2f1Sqol1WgfJ8gOqp60fojpc9Wxch7x+BA63g4JfMV5/M5x0sI0TLlLY8EBSglcr8wQF/7C80AQ==} - '@cspell/dict-git@3.0.0': - resolution: {integrity: sha512-simGS/lIiXbEaqJu9E2VPoYW1OTC2xrwPPXNXFMa2uo/50av56qOuaxDrZ5eH1LidFXwoc8HROCHYeKoNrDLSw==} - '@cspell/dict-git@3.0.4': resolution: {integrity: sha512-C44M+m56rYn6QCsLbiKiedyPTMZxlDdEYAsPwwlL5bhMDDzXZ3Ic8OCQIhMbiunhCOJJT+er4URmOmM+sllnjg==} - '@cspell/dict-golang@6.0.13': - resolution: {integrity: sha512-uBUWi+AjFpluB6qF0rsC1gGyooqXeKPUdWHSmSXW/DCnS5PBSjRW6VWWp8efc1Fanob0QJxiZiYlc4U7oxuG6Q==} - '@cspell/dict-golang@6.0.18': resolution: {integrity: sha512-Mt+7NwfodDwUk7423DdaQa0YaA+4UoV3XSxQwZioqjpFBCuxfvvv4l80MxCTAAbK6duGj0uHbGTwpv8fyKYPKg==} - '@cspell/dict-google@1.0.1': - resolution: {integrity: sha512-dQr4M3n95uOhtloNSgB9tYYGXGGEGEykkFyRtfcp5pFuEecYUa0BSgtlGKx9RXVtJtKgR+yFT/a5uQSlt8WjqQ==} + '@cspell/dict-golang@6.0.20': + resolution: {integrity: sha512-b7nd9XXs+apMMzNSWorjirQsbmlwcTC0ViQJU8u+XNose3z0y7oNeEpbTPTVoN1+1sO9aOHuFwfwoOMFCDS14Q==} '@cspell/dict-google@1.0.8': resolution: {integrity: sha512-BnMHgcEeaLyloPmBs8phCqprI+4r2Jb8rni011A8hE+7FNk7FmLE3kiwxLFrcZnnb7eqM0agW4zUaNoB0P+z8A==} - '@cspell/dict-haskell@4.0.1': - resolution: {integrity: sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==} - '@cspell/dict-haskell@4.0.5': resolution: {integrity: sha512-s4BG/4tlj2pPM9Ha7IZYMhUujXDnI0Eq1+38UTTCpatYLbQqDwRFf2KNPLRqkroU+a44yTUAe0rkkKbwy4yRtQ==} - '@cspell/dict-html-symbol-entities@4.0.0': - resolution: {integrity: sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==} - '@cspell/dict-html-symbol-entities@4.0.3': resolution: {integrity: sha512-aABXX7dMLNFdSE8aY844X4+hvfK7977sOWgZXo4MTGAmOzR8524fjbJPswIBK7GaD3+SgFZ2yP2o0CFvXDGF+A==} '@cspell/dict-html@4.0.11': resolution: {integrity: sha512-QR3b/PB972SRQ2xICR1Nw/M44IJ6rjypwzA4jn+GH8ydjAX9acFNfc+hLZVyNe0FqsE90Gw3evLCOIF0vy1vQw==} - '@cspell/dict-html@4.0.6': - resolution: {integrity: sha512-cLWHfuOhE4wqwC12up6Doxo2u1xxVhX1A8zriR4CUD+osFQzUIcBK1ykNXppga+rt1WyypaJdTU2eV6OpzYrgQ==} - '@cspell/dict-java@5.0.11': resolution: {integrity: sha512-T4t/1JqeH33Raa/QK/eQe26FE17eUCtWu+JsYcTLkQTci2dk1DfcIKo8YVHvZXBnuM43ATns9Xs0s+AlqDeH7w==} - '@cspell/dict-java@5.0.7': - resolution: {integrity: sha512-ejQ9iJXYIq7R09BScU2y5OUGrSqwcD+J5mHFOKbduuQ5s/Eh/duz45KOzykeMLI6KHPVxhBKpUPBWIsfewECpQ==} - - '@cspell/dict-julia@1.0.1': - resolution: {integrity: sha512-4JsCLCRhhLMLiaHpmR7zHFjj1qOauzDI5ZzCNQS31TUMfsOo26jAKDfo0jljFAKgw5M2fEG7sKr8IlPpQAYrmQ==} - '@cspell/dict-julia@1.1.0': resolution: {integrity: sha512-CPUiesiXwy3HRoBR3joUseTZ9giFPCydSKu2rkh6I2nVjXnl5vFHzOMLXpbF4HQ1tH2CNfnDbUndxD+I+7eL9w==} '@cspell/dict-k8s@1.0.10': resolution: {integrity: sha512-313haTrX9prep1yWO7N6Xw4D6tvUJ0Xsx+YhCP+5YrrcIKoEw5Rtlg8R4PPzLqe6zibw6aJ+Eqq+y76Vx5BZkw==} - '@cspell/dict-k8s@1.0.6': - resolution: {integrity: sha512-srhVDtwrd799uxMpsPOQqeDJY+gEocgZpoK06EFrb4GRYGhv7lXo9Fb+xQMyQytzOW9dw4DNOEck++nacDuymg==} - '@cspell/dict-kotlin@1.1.0': resolution: {integrity: sha512-vySaVw6atY7LdwvstQowSbdxjXG6jDhjkWVWSjg1XsUckyzH1JRHXe9VahZz1i7dpoFEUOWQrhIe5B9482UyJQ==} - '@cspell/dict-latex@4.0.0': - resolution: {integrity: sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==} - '@cspell/dict-latex@4.0.3': resolution: {integrity: sha512-2KXBt9fSpymYHxHfvhUpjUFyzrmN4c4P8mwIzweLyvqntBT3k0YGZJSriOdjfUjwSygrfEwiuPI1EMrvgrOMJw==} - '@cspell/dict-lorem-ipsum@4.0.0': - resolution: {integrity: sha512-1l3yjfNvMzZPibW8A7mQU4kTozwVZVw0AvFEdy+NcqtbxH+TvbSkNMqROOFWrkD2PjnKG0+Ea0tHI2Pi6Gchnw==} - '@cspell/dict-lorem-ipsum@4.0.4': resolution: {integrity: sha512-+4f7vtY4dp2b9N5fn0za/UR0kwFq2zDtA62JCbWHbpjvO9wukkbl4rZg4YudHbBgkl73HRnXFgCiwNhdIA1JPw==} - '@cspell/dict-lua@4.0.3': - resolution: {integrity: sha512-lDHKjsrrbqPaea13+G9s0rtXjMO06gPXPYRjRYawbNmo4E/e3XFfVzeci3OQDQNDmf2cPOwt9Ef5lu2lDmwfJg==} - '@cspell/dict-lua@4.0.7': resolution: {integrity: sha512-Wbr7YSQw+cLHhTYTKV6cAljgMgcY+EUAxVIZW3ljKswEe4OLxnVJ7lPqZF5JKjlXdgCjbPSimsHqyAbC5pQN/Q==} - '@cspell/dict-makefile@1.0.0': - resolution: {integrity: sha512-3W9tHPcSbJa6s0bcqWo6VisEDTSN5zOtDbnPabF7rbyjRpNo0uHXHRJQF8gAbFzoTzBBhgkTmrfSiuyQm7vBUQ==} - '@cspell/dict-makefile@1.0.4': resolution: {integrity: sha512-E4hG/c0ekPqUBvlkrVvzSoAA+SsDA9bLi4xSV3AXHTVru7Y2bVVGMPtpfF+fI3zTkww/jwinprcU1LSohI3ylw==} @@ -1737,152 +1650,113 @@ packages: '@cspell/dict-monkeyc@1.0.10': resolution: {integrity: sha512-7RTGyKsTIIVqzbvOtAu6Z/lwwxjGRtY5RkKPlXKHEoEAgIXwfDxb5EkVwzGQwQr8hF/D3HrdYbRT8MFBfsueZw==} - '@cspell/dict-monkeyc@1.0.6': - resolution: {integrity: sha512-oO8ZDu/FtZ55aq9Mb67HtaCnsLn59xvhO/t2mLLTHAp667hJFxpp7bCtr2zOrR1NELzFXmKln/2lw/PvxMSvrA==} - - '@cspell/dict-node@5.0.1': - resolution: {integrity: sha512-lax/jGz9h3Dv83v8LHa5G0bf6wm8YVRMzbjJPG/9rp7cAGPtdrga+XANFq+B7bY5+jiSA3zvj10LUFCFjnnCCg==} - '@cspell/dict-node@5.0.6': resolution: {integrity: sha512-CEbhPCpxGvRNByGolSBTrXXW2rJA4bGqZuTx1KKO85mwR6aadeOmUE7xf/8jiCkXSy+qvr9aJeh+jlfXcsrziQ==} '@cspell/dict-npm@5.1.26': resolution: {integrity: sha512-JU0/9P4nLPPC3Py+sF42tUKm9J4KAvwXaJubp2a4QwhCPzFVlOJTP2tTseFlLbdZn23d61pt0hZ+Jhyy7N76Mg==} - '@cspell/dict-npm@5.1.5': - resolution: {integrity: sha512-oAOGWuJYU3DlO+cAsStKMWN8YEkBue25cRC9EwdiL5Z84nchU20UIoYrLfIQejMlZca+1GyrNeyxRAgn4KiivA==} - - '@cspell/dict-php@4.0.10': - resolution: {integrity: sha512-NfTZdp6kcZDF1PvgQ6cY0zE4FUO5rSwNmBH/iwCBuaLfJAFQ97rgjxo+D2bic4CFwNjyHutnHPtjJBRANO5XQw==} + '@cspell/dict-npm@5.1.34': + resolution: {integrity: sha512-UrUYqRQX864Cx9QJkg7eEIxmjYGqcje+x1j7bzl+a3jCKwT6jm+p0off6VEOf3EReHP0dWUSYO3Q0+pLL/N+FQ==} '@cspell/dict-php@4.0.14': resolution: {integrity: sha512-7zur8pyncYZglxNmqsRycOZ6inpDoVd4yFfz1pQRe5xaRWMiK3Km4n0/X/1YMWhh3e3Sl/fQg5Axb2hlN68t1g==} - '@cspell/dict-powershell@5.0.10': - resolution: {integrity: sha512-U4H0zm94sNK+YP7jSFb7xb160XLf2dKIPVt5sOYctKlEyR9M16sP8FHbyWV2Yp1YtxXugoNdeCm2vwGEDAd8sg==} - '@cspell/dict-powershell@5.0.14': resolution: {integrity: sha512-ktjjvtkIUIYmj/SoGBYbr3/+CsRGNXGpvVANrY0wlm/IoGlGywhoTUDYN0IsGwI2b8Vktx3DZmQkfb3Wo38jBA==} '@cspell/dict-public-licenses@2.0.13': resolution: {integrity: sha512-1Wdp/XH1ieim7CadXYE7YLnUlW0pULEjVl9WEeziZw3EKCAw8ZI8Ih44m4bEa5VNBLnuP5TfqC4iDautAleQzQ==} - '@cspell/dict-public-licenses@2.0.8': - resolution: {integrity: sha512-Sup+tFS7cDV0fgpoKtUqEZ6+fA/H+XUgBiqQ/Fbs6vUE3WCjJHOIVsP+udHuyMH7iBfJ4UFYOYeORcY4EaKdMg==} - '@cspell/dict-python@4.2.15': resolution: {integrity: sha512-VNXhj0Eh+hdHN89MgyaoSAexBQKmYtJaMhucbMI7XmBs4pf8fuFFN3xugk51/A4TZJr8+RImdFFsGMOw+I4bDA==} - '@cspell/dict-python@4.2.8': - resolution: {integrity: sha512-4y5dynLiajvowhB3PqlcwJ2C4okK1y2Hombec1+TGcV9sUBfo8FYNw6VRFUUrpsxO+Ut/3ncIifdZS5/zAWi5w==} - - '@cspell/dict-r@2.0.1': - resolution: {integrity: sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==} + '@cspell/dict-python@4.2.17': + resolution: {integrity: sha512-xqMKfVc8d7yDaOChFdL2uWAN3Mw9qObB/Zr6t5w1OHbi23gWs7V1lI9d0mXAoqSK6N3mosbum4OIq/FleQDnlw==} '@cspell/dict-r@2.1.0': resolution: {integrity: sha512-k2512wgGG0lTpTYH9w5Wwco+lAMf3Vz7mhqV8+OnalIE7muA0RSuD9tWBjiqLcX8zPvEJr4LdgxVju8Gk3OKyA==} - '@cspell/dict-ruby@5.0.4': - resolution: {integrity: sha512-URw0jScj5pv8sKCVLNnde11qVCQR442rUpSd12u46Swl+5qBaSdnOUoCWQk419kd9/dpC6bB/3l4kOSY2fdYHw==} - '@cspell/dict-ruby@5.0.7': resolution: {integrity: sha512-4/d0hcoPzi5Alk0FmcyqlzFW9lQnZh9j07MJzPcyVO62nYJJAGKaPZL2o4qHeCS/od/ctJC5AHRdoUm0ktsw6Q==} + '@cspell/dict-ruby@5.0.8': + resolution: {integrity: sha512-ixuTneU0aH1cPQRbWJvtvOntMFfeQR2KxT8LuAv5jBKqQWIHSxzGlp+zX3SVyoeR0kOWiu64/O5Yn836A5yMcQ==} + '@cspell/dict-rust@4.0.11': resolution: {integrity: sha512-OGWDEEzm8HlkSmtD8fV3pEcO2XBpzG2XYjgMCJCRwb2gRKvR+XIm6Dlhs04N/K2kU+iH8bvrqNpM8fS/BFl0uw==} - '@cspell/dict-rust@4.0.6': - resolution: {integrity: sha512-Buzy9PfLbdRPibSth8CV1D8ZsYqybo26yNIlAN+8ehU0pSBss0Jv4aleL4vKQ3FjouXeAC27rtEsLd7yaMZTog==} - - '@cspell/dict-scala@5.0.3': - resolution: {integrity: sha512-4yGb4AInT99rqprxVNT9TYb1YSpq58Owzq7zi3ZS5T0u899Y4VsxsBiOgHnQ/4W+ygi+sp+oqef8w8nABR2lkg==} - '@cspell/dict-scala@5.0.7': resolution: {integrity: sha512-yatpSDW/GwulzO3t7hB5peoWwzo+Y3qTc0pO24Jf6f88jsEeKmDeKkfgPbYuCgbE4jisGR4vs4+jfQZDIYmXPA==} '@cspell/dict-shell@1.1.0': resolution: {integrity: sha512-D/xHXX7T37BJxNRf5JJHsvziFDvh23IF/KvkZXNSh8VqcRdod3BAz9VGHZf6VDqcZXr1VRqIYR3mQ8DSvs3AVQ==} - '@cspell/dict-software-terms@4.1.7': - resolution: {integrity: sha512-+fFTALseXszDN8/khonF1DpTcYzwyNqYxhATLakr7CUPtUCO1fCH4lidMtBN4UtPVpE6tbjc5D8tj51PJxEOcw==} - '@cspell/dict-software-terms@4.2.5': resolution: {integrity: sha512-CaRzkWti3AgcXoxuRcMijaNG7YUk/MH1rHjB8VX34v3UdCxXXeqvRyElRKnxhFeVLB/robb2UdShqh/CpskxRg==} - '@cspell/dict-sql@2.1.5': - resolution: {integrity: sha512-FmxanytHXss7GAWAXmgaxl3icTCW7YxlimyOSPNfm+njqeUDjw3kEv4mFNDDObBJv8Ec5AWCbUDkWIpkE3IpKg==} + '@cspell/dict-software-terms@5.0.5': + resolution: {integrity: sha512-ZjAOa8FI8/JrxaRqKT3eS7AQXFjU174xxQoKYMkmdwSyNIj7WUCAg10UeLqeMjFVv36zIO0Hm0dD2+Bvn18SLA==} '@cspell/dict-sql@2.2.0': resolution: {integrity: sha512-MUop+d1AHSzXpBvQgQkCiok8Ejzb+nrzyG16E8TvKL2MQeDwnIvMe3bv90eukP6E1HWb+V/MA/4pnq0pcJWKqQ==} - '@cspell/dict-svelte@1.0.2': - resolution: {integrity: sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==} - '@cspell/dict-svelte@1.0.6': resolution: {integrity: sha512-8LAJHSBdwHCoKCSy72PXXzz7ulGROD0rP1CQ0StOqXOOlTUeSFaJJlxNYjlONgd2c62XBQiN2wgLhtPN+1Zv7Q==} - '@cspell/dict-swift@2.0.1': - resolution: {integrity: sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==} - '@cspell/dict-swift@2.0.5': resolution: {integrity: sha512-3lGzDCwUmnrfckv3Q4eVSW3sK3cHqqHlPprFJZD4nAqt23ot7fic5ALR7J4joHpvDz36nHX34TgcbZNNZOC/JA==} - '@cspell/dict-terraform@1.0.2': - resolution: {integrity: sha512-UZdJwWIpib2Rx02w6vtXTU3z+M/VMZU0F1dhSL3Ab9otQsFntT8U1CX7wBSqQCLg8bJiCfnUyVvMK3UBm3SR8A==} - '@cspell/dict-terraform@1.1.0': resolution: {integrity: sha512-G55pcUUxeXAhejstmD35B47SkFd4uqCQimc+CMgq8Nx0dr03guL2iMsz8faRWQGkCnGimX8S91rbOhDv9p/heg==} - '@cspell/dict-typescript@3.1.6': - resolution: {integrity: sha512-1beC6O4P/j23VuxX+i0+F7XqPVc3hhiAzGJHEKqnWf5cWAXQtg0xz3xQJ5MvYx2a7iLaSa+lu7+05vG9UHyu9Q==} + '@cspell/dict-terraform@1.1.1': + resolution: {integrity: sha512-07KFDwCU7EnKl4hOZLsLKlj6Zceq/IsQ3LRWUyIjvGFfZHdoGtFdCp3ZPVgnFaAcd/DKv+WVkrOzUBSYqHopQQ==} '@cspell/dict-typescript@3.2.0': resolution: {integrity: sha512-Pk3zNePLT8qg51l0M4g1ISowYAEGxTuNfZlgkU5SvHa9Cu7x/BWoyYq9Fvc3kAyoisCjRPyvWF4uRYrPitPDFw==} - '@cspell/dict-vue@3.0.0': - resolution: {integrity: sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==} - '@cspell/dict-vue@3.0.4': resolution: {integrity: sha512-0dPtI0lwHcAgSiQFx8CzvqjdoXROcH+1LyqgROCpBgppommWpVhbQ0eubnKotFEXgpUCONVkeZJ6Ql8NbTEu+w==} - '@cspell/dynamic-import@8.14.4': - resolution: {integrity: sha512-GjKsBJvPXp4dYRqsMn7n1zpnKbnpfJnlKLOVeoFBh8fi4n06G50xYr+G25CWX1WT3WFaALAavvVICEUPrVsuqg==} - engines: {node: '>=18.0'} - '@cspell/dynamic-import@8.17.4': resolution: {integrity: sha512-rUwFOVPnfEGzhzCRnE4esTTMgWtTORXfa5FJJR8653KwcvD6HJQfPTYepBG6n6Bmu3TssMa4ktq+ZJk4o1BF9A==} engines: {node: '>=18.0'} - '@cspell/eslint-plugin@8.14.4': - resolution: {integrity: sha512-Wv6Jkttp/rsEm1nadLFQrUrYg9nTWQFwJu47KO2cfWP39TeH0zXQpmyas1xNlcDx5QJ9JJw9urTT/iw2tsHeRA==} + '@cspell/dynamic-import@8.18.1': + resolution: {integrity: sha512-VJHfS/Iv0Rx7wn1pjPmwgsaw6r72N5Cx2gL0slWk8Cogc8YiK7/6jsGnsvxJZVkHntJoiT8PrkIvhNKb3awD3g==} + engines: {node: '>=18.0'} + + '@cspell/eslint-plugin@8.18.1': + resolution: {integrity: sha512-Knlp6M5zGKkjZSFPhsLZoARS8vbSiePK6AkNXujmlxM91KyHJsAEJiyAVnR5qwhYcsOkcngmO+pmLir+WjHlAw==} engines: {node: '>=18'} peerDependencies: eslint: ^7 || ^8 || ^9 - '@cspell/filetypes@8.14.4': - resolution: {integrity: sha512-qd68dD7xTA4Mnf/wjIKYz2SkiTBshIM+yszOUtLa06YJm0aocoNQ25FHXyYEQYm9NQXCYnRWWA02sFMGs8Sv/w==} - engines: {node: '>=18'} - '@cspell/filetypes@8.17.4': resolution: {integrity: sha512-zzYm0hr+lvctsy/65hjI0vsQJj2CAwSOTnVk+5ubJCkCaWH/rayI/SaVZA0Xynf08B/x0r/36nPH0lO2iMJ4aw==} engines: {node: '>=18'} - '@cspell/strong-weak-map@8.14.4': - resolution: {integrity: sha512-Uyfck64TfVU24wAP3BLGQ5EsAfzIZiLfN90NhttpEM7GlOBmbGrEJd4hNOwfpYsE/TT80eGWQVPRTLr5SDbXFA==} + '@cspell/filetypes@8.18.1': + resolution: {integrity: sha512-vTOb2itP0pjrccvt8wcKiTGyw0pFMTPI85H12T6n8ZhqXTktPgQH2gEf/SU/5tkPNnBKr4GJ+FdU5hJ27HzgXQ==} engines: {node: '>=18'} '@cspell/strong-weak-map@8.17.4': resolution: {integrity: sha512-Io4ffbMI9hQz+9CLe/oU1Om0H3SqAlvFTaS7ZQOg7joyJSXuGBsCcCg03uTRKWD+NoaxPNUlZOkucUBGil6djw==} engines: {node: '>=18'} - '@cspell/url@8.14.4': - resolution: {integrity: sha512-htHhNF8WrM/NfaLSWuTYw0NqVgFRVHYSyHlRT3i/Yv5xvErld8Gw7C6ldm+0TLjoGlUe6X1VV72JSir7+yLp/Q==} - engines: {node: '>=18.0'} + '@cspell/strong-weak-map@8.18.1': + resolution: {integrity: sha512-gsgv+5ZQD4aHNHDdfNGoafVYkqRynyYgaodt9Dp/3o0YKYcxGf2jrX8SJ35MfZ61qln0n7P4Djrg+bFV2zNH5w==} + engines: {node: '>=18'} '@cspell/url@8.17.4': resolution: {integrity: sha512-vWLySh0ARsI0+TdvA8W6btdeeQbSjBhDE8kwGlzIrOCLIfkeO9Bu++mkc1To1/uogkS2T5icmA24D0rL8ZqjNw==} engines: {node: '>=18.0'} + '@cspell/url@8.18.1': + resolution: {integrity: sha512-FRJbLYDC9ucpTOzbF6MohP2u5X3NU5L0RoVuoYCynqm/QOI38XP6WOEaI4H58CAn857bOIKZk0LZRPTGzi6Qlg==} + engines: {node: '>=18.0'} + '@csstools/color-helpers@5.0.1': resolution: {integrity: sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==} engines: {node: '>=18'} @@ -1969,8 +1843,8 @@ packages: '@emnapi/runtime@1.3.1': resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} - '@es-joy/jsdoccomment@0.48.0': - resolution: {integrity: sha512-G6QUWIcC+KvSwXNsJyDTHvqUdNoAVJPPgkc3+Uk4WBKqZvoXhlvazOgm9aL0HwihJLQf0l+tOE2UFzXBqCqgDw==} + '@es-joy/jsdoccomment@0.49.0': + resolution: {integrity: sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==} engines: {node: '>=16'} '@esbuild/aix-ppc64@0.21.5': @@ -2411,12 +2285,6 @@ packages: cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.4.1': - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/eslint-utils@4.5.1': resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2427,28 +2295,24 @@ packages: resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.19.2': - resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} + '@eslint/config-array@0.20.0': + resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.11.0': - resolution: {integrity: sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA==} + '@eslint/config-helpers@0.2.1': + resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/core@0.12.0': resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.2.0': - resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.12.0': - resolution: {integrity: sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/js@9.20.0': - resolution: {integrity: sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==} + '@eslint/js@9.24.0': + resolution: {integrity: sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': @@ -2791,6 +2655,10 @@ packages: resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@pkgr/core@0.2.1': + resolution: {integrity: sha512-VzgHzGblFmUeBmmrk55zPyrQIArQN4vujc9shWytaPdB3P7qhi0cpaiKIr7tlCmFv2lYUwnLospIqjL9ZSAhhg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@polka/url@1.0.0-next.28': resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} @@ -3372,35 +3240,35 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.24.1': - resolution: {integrity: sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA==} + '@typescript-eslint/eslint-plugin@8.29.1': + resolution: {integrity: sha512-ba0rr4Wfvg23vERs3eB+P3lfj2E+2g3lhWcCVukUuhtcdUx5lSIFZlGFEBHKr+3zizDa/TvZTptdNHVZWAkSBg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.24.1': - resolution: {integrity: sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ==} + '@typescript-eslint/parser@8.29.1': + resolution: {integrity: sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' '@typescript-eslint/scope-manager@8.24.1': resolution: {integrity: sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.8.1': - resolution: {integrity: sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==} + '@typescript-eslint/scope-manager@8.29.1': + resolution: {integrity: sha512-2nggXGX5F3YrsGN08pw4XpMLO1Rgtnn4AzTegC2MDesv6q3QaTU5yU7IbS1tf1IwCR0Hv/1EFygLn9ms6LIpDA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.24.1': - resolution: {integrity: sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw==} + '@typescript-eslint/type-utils@8.29.1': + resolution: {integrity: sha512-DkDUSDwZVCYN71xA4wzySqqcZsHKic53A4BLqmrWFFpOpNSoxX233lwGu/2135ymTCR04PoKiEEEvN1gFYg4Tw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' '@typescript-eslint/types@7.18.0': resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} @@ -3410,8 +3278,8 @@ packages: resolution: {integrity: sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.8.1': - resolution: {integrity: sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==} + '@typescript-eslint/types@8.29.1': + resolution: {integrity: sha512-VT7T1PuJF1hpYC3AGm2rCgJBjHL3nc+A/bhOp9sGMKfi5v0WufsX/sHCFBfNTx2F+zA6qBc/PD0/kLRLjdt8mQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/typescript-estree@7.18.0': @@ -3429,14 +3297,11 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/typescript-estree@8.8.1': - resolution: {integrity: sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==} + '@typescript-eslint/typescript-estree@8.29.1': + resolution: {integrity: sha512-l1enRoSaUkQxOQnbi0KPUtqeZkSiFlqrx9/3ns2rEDhGKfTa+88RmXqedC1zmVTOWrLc2e6DEJrTA51C9iLH5g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + typescript: '>=4.8.4 <5.9.0' '@typescript-eslint/utils@8.24.1': resolution: {integrity: sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==} @@ -3445,11 +3310,12 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.8.0' - '@typescript-eslint/utils@8.8.1': - resolution: {integrity: sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==} + '@typescript-eslint/utils@8.29.1': + resolution: {integrity: sha512-QAkFEbytSaB8wnmB+DflhUPz6CLbFWE2SnSCrRMEa+KnXIzDYbpsn++1HGvnfAsUY44doDXmvRkO5shlM/3UfA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' '@typescript-eslint/visitor-keys@7.18.0': resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} @@ -3459,8 +3325,8 @@ packages: resolution: {integrity: sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.8.1': - resolution: {integrity: sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==} + '@typescript-eslint/visitor-keys@8.29.1': + resolution: {integrity: sha512-RGLh5CRaUEf02viP5c1Vh1cMGffQscyHe7HPAzGpfmfflFg1wUz2rYxd+OZqwpeypYvZ8UxSxuIpF++fmOzEcg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.3.0': @@ -4675,69 +4541,69 @@ packages: resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} engines: {node: '>=8'} - cspell-config-lib@8.14.4: - resolution: {integrity: sha512-cnUeJfniTiebqCaQmIUnbSrPrTH7xzKRQjJDHAEV0WYnOG2MhRXI13OzytdFdhkVBdStmgTzTCJKE7x+kmU2NA==} - engines: {node: '>=18'} - cspell-config-lib@8.17.4: resolution: {integrity: sha512-vOi3B5gnngGeI1HMVDosHTBCRROx7XQXpD6rcKFxxehrs3hw1/EGGEKPKWX5R1UKhOiUNVmvicpqTXU+4/tbZA==} engines: {node: '>=18'} - cspell-dictionary@8.14.4: - resolution: {integrity: sha512-pZvQHxpAW5fZAnt3ZKKy3s7M+3CX2t8tCS3uJrpEHIynlCawpG0fPF78rVE5o+g0dON36Lguc/BUuSN4IWKLmQ==} + cspell-config-lib@8.18.1: + resolution: {integrity: sha512-zdJ0uhLROSUrHoibysPw+AkxKPUmiG95hDtiL7s8smewkuaS1hpjqwsDBx981nHYs3xW3qDUfVATrAkSzb0VMw==} engines: {node: '>=18'} cspell-dictionary@8.17.4: resolution: {integrity: sha512-nzFc/+r6Q0wP5KpvKnjtnI+C2HMaLfrzMaY4VtoCzyqEF8inYQz430e6sSReBDzjshoU9YUxhShXl18aA3eAqA==} engines: {node: '>=18'} + cspell-dictionary@8.18.1: + resolution: {integrity: sha512-vKHEPSfkMKMR4S4tk6K2vHC+f3kdJK8Kdh/C0jDh6RRDjDsyAPxshtbremxOgAX6X8GaRUCROoMZ7FhB92+Y9w==} + engines: {node: '>=18'} + cspell-gitignore@8.17.4: resolution: {integrity: sha512-9KwnXwNwE1eXYRyqHAMFPowJd3yFh2pQnnrfdQRvdculqFY39G4g/d4OQV9W/iMpcednL9K01IhxuUvbF7ZrIA==} engines: {node: '>=18'} hasBin: true - cspell-glob@8.14.4: - resolution: {integrity: sha512-C/xTS5nujMRMuguibq92qMVP767mtxrur7DcVolCvpzcivm1RB5NtIN0OctQxTyMbnmKeQv1t4epRKQ9A8vWRg==} - engines: {node: '>=18'} - cspell-glob@8.17.4: resolution: {integrity: sha512-HbAyg/t6l2Um0kgeTZeTEyXgVkIQX/ir2uLW/W3T9foOkSZ016Os6GRYDRJX7ebfREk8cCZ0uFtOi1Yn56INEQ==} engines: {node: '>=18'} - cspell-grammar@8.14.4: - resolution: {integrity: sha512-yaSKAAJDiamsw3FChbw4HXb2RvTQrDsLelh1+T4MavarOIcAxXrqAJ8ysqm++g+S/ooJz2YO8YWIyzJKxcMf8g==} + cspell-glob@8.18.1: + resolution: {integrity: sha512-tlZXvzsN7dByHo69dz/HbJuQDUtrfhdioZ/LHaW7W9diG9NpaghgEfyX4fmsIXjU/2f66LDpYVY6osjtlOgyrg==} engines: {node: '>=18'} - hasBin: true cspell-grammar@8.17.4: resolution: {integrity: sha512-RgnpQPVSOdWxq7fLHUkjGJCkMNay4p2cZXRYwhTBJf2kWNsDC39tjRhugFweyxxZPamEbLERgkCaFzE54enuMw==} engines: {node: '>=18'} hasBin: true - cspell-io@8.14.4: - resolution: {integrity: sha512-o6OTWRyx/Az+PFhr1B0wMAwqG070hFC9g73Fkxd8+rHX0rfRS69QZH7LgSmZytqbZIMxCTDGdsLl33MFGWCbZQ==} + cspell-grammar@8.18.1: + resolution: {integrity: sha512-V6XTN1B++7EzJA0H4g4XbNJtqm6Y3/iXdLeZ6sMRDaNFKXXwTbWRtn8gukDQIytyw09AnCUKeqGSzCVqw26Omg==} engines: {node: '>=18'} + hasBin: true cspell-io@8.17.4: resolution: {integrity: sha512-lHvkxquov5XfIXSenzXrWcOWPiW79+uySoExb20UXHvPSMz0Bk7ZIqDf6lMwTquXbM4BvGGsKQbQE/D4SLD9jw==} engines: {node: '>=18'} - cspell-lib@8.14.4: - resolution: {integrity: sha512-qdkUkKtm+nmgpA4jQbmQTuepDfjHBDWvs3zDuEwVIVFq/h8gnXrRr75gJ3RYdTy+vOOqHPoLLqgxyqkUUrUGXA==} + cspell-io@8.18.1: + resolution: {integrity: sha512-mm9SUEF2yShuTXDSjCbsAqYTEb6jrtgcCnlqIzpsZOJOOe+zj/VyzTy2NJvOrdvR59dikdaqB75VGBMfHi804g==} engines: {node: '>=18'} cspell-lib@8.17.4: resolution: {integrity: sha512-BxQy4MDFSjMQ74SYptWJOLLPsNC8XDtKyey0IfMQaqeFmuxrz727GWcONQ2KROrPPs9dnmccDs6Kn8Tx7Wug4A==} engines: {node: '>=18'} - cspell-trie-lib@8.14.4: - resolution: {integrity: sha512-zu8EJ33CH+FA5lwTRGqS//Q6phO0qtgEmODMR1KPlD7WlrfTFMb3bWFsLo/tiv5hjpsn7CM6dYDAAgBOSkoyhQ==} + cspell-lib@8.18.1: + resolution: {integrity: sha512-t1j+XB7515yHmrczK6I1N6j0a72vmL/6OxsMJnCucHC6DO0WkOqmHulNRH7LpFacnns0dx15lmrAqPg7gQFcIg==} engines: {node: '>=18'} cspell-trie-lib@8.17.4: resolution: {integrity: sha512-Ou2MGBnZyC+Hti57m4T4D/Tq1P3G570rFPkxgi32f325xsLz1AVEvqrM5oVHDilFH2guUYFaelmL0UcGeP3L6w==} engines: {node: '>=18'} + cspell-trie-lib@8.18.1: + resolution: {integrity: sha512-UaB36wsyp2eWeMtrbS6Q2t2WFvpedmGXJ879yHn9qKD7ViyUpI4cAbh6v7gWMUu+gjqCulXtke64k1ddmBihPQ==} + engines: {node: '>=18'} + cspell@8.17.4: resolution: {integrity: sha512-cQ6KyYB7itXxc+roxvozIKksbOyBO1NY5Dt5RWHl1Uh4OO++RJAKxmVWrY0g1ubBxKWGXk8TvuunK1+L/jvjIQ==} engines: {node: '>=18'} @@ -5410,14 +5276,14 @@ packages: engines: {node: '>=6.0'} hasBin: true - eslint-config-prettier@10.0.1: - resolution: {integrity: sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==} + eslint-config-prettier@10.1.1: + resolution: {integrity: sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==} hasBin: true peerDependencies: eslint: '>=7.0.0' - eslint-plugin-cypress@4.1.0: - resolution: {integrity: sha512-JhqkMY02mw74USwK9OFhectx3YSj6Co1NgWBxlGdKvlqiAp9vdEuQqt33DKGQFvvGS/NWtduuhWXWNnU29xDSg==} + eslint-plugin-cypress@4.2.1: + resolution: {integrity: sha512-WNhKkQPqXcbDL7pxGnNYBVLlAIOk6eHdFGQFRELsba871guZZe8zZe50GAjBXSZKcvUWbzCUopM+8ArlngdyGQ==} peerDependencies: eslint: '>=9' @@ -5425,8 +5291,8 @@ packages: resolution: {integrity: sha512-pbRchDV2SmqbCi/Ev/q3aAikzG9BcFe0IjjqjtMn8eTLq71ZUggyJB6CDmuwGAXmYZHrXI12XTfCqvgcnPRqGw==} engines: {node: '>=16.0.0'} - eslint-plugin-jest@28.8.3: - resolution: {integrity: sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==} + eslint-plugin-jest@28.11.0: + resolution: {integrity: sha512-QAfipLcNCWLVocVbZW8GimKn5p5iiMcgGbRzz8z/P5q7xw+cNEpYqyzFMtIF/ZgF2HLOyy+dYBut+DoYolvqig==} engines: {node: ^16.10.0 || ^18.12.0 || >=20.0.0} peerDependencies: '@typescript-eslint/eslint-plugin': ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -5438,8 +5304,8 @@ packages: jest: optional: true - eslint-plugin-jsdoc@50.3.2: - resolution: {integrity: sha512-TjgZocG53N3a84PdCFGqVMWLWwDitOUuKjlJftwTu/iTiD7N/Q2Q3eEy/Q4GfJqpM4rTJCkzUYWQfol6RZNDcA==} + eslint-plugin-jsdoc@50.6.9: + resolution: {integrity: sha512-7/nHu3FWD4QRG8tCVqcv+BfFtctUtEDWc29oeDXB4bwmDM2/r1ndl14AG/2DUntdqH7qmpvdemJKwb3R97/QEw==} engines: {node: '>=18'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 @@ -5477,8 +5343,8 @@ packages: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} - eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} + eslint-scope@8.3.0: + resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: @@ -5489,8 +5355,8 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.20.1: - resolution: {integrity: sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g==} + eslint@9.24.0: + resolution: {integrity: sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -5638,10 +5504,6 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-equals@5.0.1: - resolution: {integrity: sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==} - engines: {node: '>=6.0.0'} - fast-equals@5.2.2: resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==} engines: {node: '>=6.0.0'} @@ -6275,10 +6137,6 @@ packages: resolution: {integrity: sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==} engines: {node: '>= 4'} - import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -8913,6 +8771,10 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + synckit@0.10.3: + resolution: {integrity: sha512-R1urvuyiTaWfeCggqEvpDJwAlDVdsT9NM+IP//Tk2x7qHCkSvBk/fwFgw/TLAHzZlrAnnazMcRw0ZD8HlYFTEQ==} + engines: {node: ^14.18.0 || >=16.0.0} + synckit@0.9.2: resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -9199,12 +9061,12 @@ packages: peerDependencies: typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x - typescript-eslint@8.24.1: - resolution: {integrity: sha512-cw3rEdzDqBs70TIcb0Gdzbt6h11BSs2pS0yaq7hDWDBtCCSei1pPSUXE9qUdQ/Wm9NgFg8mKtMt1b8fTHIl1jA==} + typescript-eslint@8.29.1: + resolution: {integrity: sha512-f8cDkvndhbQMPcysk6CUSGBWV+g1utqdn71P5YKwMumVMOG/5k7cHq0KyG4O52nB0oKS4aN2Tp5+wB4APJGC+w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' typescript@5.7.3: resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} @@ -11319,62 +11181,6 @@ snapshots: '@colors/colors@1.5.0': optional: true - '@cspell/cspell-bundled-dicts@8.14.4': - dependencies: - '@cspell/dict-ada': 4.0.2 - '@cspell/dict-aws': 4.0.4 - '@cspell/dict-bash': 4.1.5 - '@cspell/dict-companies': 3.1.4 - '@cspell/dict-cpp': 5.1.19 - '@cspell/dict-cryptocurrencies': 5.0.0 - '@cspell/dict-csharp': 4.0.2 - '@cspell/dict-css': 4.0.13 - '@cspell/dict-dart': 2.2.1 - '@cspell/dict-django': 4.1.0 - '@cspell/dict-docker': 1.1.7 - '@cspell/dict-dotnet': 5.0.5 - '@cspell/dict-elixir': 4.0.3 - '@cspell/dict-en-common-misspellings': 2.0.4 - '@cspell/dict-en-gb': 1.1.33 - '@cspell/dict-en_us': 4.3.23 - '@cspell/dict-filetypes': 3.0.4 - '@cspell/dict-flutter': 1.0.0 - '@cspell/dict-fonts': 4.0.0 - '@cspell/dict-fsharp': 1.0.1 - '@cspell/dict-fullstack': 3.2.0 - '@cspell/dict-gaming-terms': 1.0.5 - '@cspell/dict-git': 3.0.0 - '@cspell/dict-golang': 6.0.13 - '@cspell/dict-google': 1.0.1 - '@cspell/dict-haskell': 4.0.1 - '@cspell/dict-html': 4.0.6 - '@cspell/dict-html-symbol-entities': 4.0.0 - '@cspell/dict-java': 5.0.7 - '@cspell/dict-julia': 1.0.1 - '@cspell/dict-k8s': 1.0.6 - '@cspell/dict-latex': 4.0.0 - '@cspell/dict-lorem-ipsum': 4.0.0 - '@cspell/dict-lua': 4.0.3 - '@cspell/dict-makefile': 1.0.0 - '@cspell/dict-monkeyc': 1.0.6 - '@cspell/dict-node': 5.0.1 - '@cspell/dict-npm': 5.1.5 - '@cspell/dict-php': 4.0.10 - '@cspell/dict-powershell': 5.0.10 - '@cspell/dict-public-licenses': 2.0.8 - '@cspell/dict-python': 4.2.8 - '@cspell/dict-r': 2.0.1 - '@cspell/dict-ruby': 5.0.4 - '@cspell/dict-rust': 4.0.6 - '@cspell/dict-scala': 5.0.3 - '@cspell/dict-software-terms': 4.1.7 - '@cspell/dict-sql': 2.1.5 - '@cspell/dict-svelte': 1.0.2 - '@cspell/dict-swift': 2.0.1 - '@cspell/dict-terraform': 1.0.2 - '@cspell/dict-typescript': 3.1.6 - '@cspell/dict-vue': 3.0.0 - '@cspell/cspell-bundled-dicts@8.17.4': dependencies: '@cspell/dict-ada': 4.1.0 @@ -11436,176 +11242,179 @@ snapshots: '@cspell/dict-typescript': 3.2.0 '@cspell/dict-vue': 3.0.4 + '@cspell/cspell-bundled-dicts@8.18.1': + dependencies: + '@cspell/dict-ada': 4.1.0 + '@cspell/dict-al': 1.1.0 + '@cspell/dict-aws': 4.0.9 + '@cspell/dict-bash': 4.2.0 + '@cspell/dict-companies': 3.1.14 + '@cspell/dict-cpp': 6.0.7 + '@cspell/dict-cryptocurrencies': 5.0.4 + '@cspell/dict-csharp': 4.0.6 + '@cspell/dict-css': 4.0.17 + '@cspell/dict-dart': 2.3.0 + '@cspell/dict-data-science': 2.0.7 + '@cspell/dict-django': 4.1.4 + '@cspell/dict-docker': 1.1.12 + '@cspell/dict-dotnet': 5.0.9 + '@cspell/dict-elixir': 4.0.7 + '@cspell/dict-en-common-misspellings': 2.0.10 + '@cspell/dict-en-gb': 1.1.33 + '@cspell/dict-en_us': 4.4.0 + '@cspell/dict-filetypes': 3.0.11 + '@cspell/dict-flutter': 1.1.0 + '@cspell/dict-fonts': 4.0.4 + '@cspell/dict-fsharp': 1.1.0 + '@cspell/dict-fullstack': 3.2.6 + '@cspell/dict-gaming-terms': 1.1.0 + '@cspell/dict-git': 3.0.4 + '@cspell/dict-golang': 6.0.20 + '@cspell/dict-google': 1.0.8 + '@cspell/dict-haskell': 4.0.5 + '@cspell/dict-html': 4.0.11 + '@cspell/dict-html-symbol-entities': 4.0.3 + '@cspell/dict-java': 5.0.11 + '@cspell/dict-julia': 1.1.0 + '@cspell/dict-k8s': 1.0.10 + '@cspell/dict-kotlin': 1.1.0 + '@cspell/dict-latex': 4.0.3 + '@cspell/dict-lorem-ipsum': 4.0.4 + '@cspell/dict-lua': 4.0.7 + '@cspell/dict-makefile': 1.0.4 + '@cspell/dict-markdown': 2.0.9(@cspell/dict-css@4.0.17)(@cspell/dict-html-symbol-entities@4.0.3)(@cspell/dict-html@4.0.11)(@cspell/dict-typescript@3.2.0) + '@cspell/dict-monkeyc': 1.0.10 + '@cspell/dict-node': 5.0.6 + '@cspell/dict-npm': 5.1.34 + '@cspell/dict-php': 4.0.14 + '@cspell/dict-powershell': 5.0.14 + '@cspell/dict-public-licenses': 2.0.13 + '@cspell/dict-python': 4.2.17 + '@cspell/dict-r': 2.1.0 + '@cspell/dict-ruby': 5.0.8 + '@cspell/dict-rust': 4.0.11 + '@cspell/dict-scala': 5.0.7 + '@cspell/dict-shell': 1.1.0 + '@cspell/dict-software-terms': 5.0.5 + '@cspell/dict-sql': 2.2.0 + '@cspell/dict-svelte': 1.0.6 + '@cspell/dict-swift': 2.0.5 + '@cspell/dict-terraform': 1.1.1 + '@cspell/dict-typescript': 3.2.0 + '@cspell/dict-vue': 3.0.4 + '@cspell/cspell-json-reporter@8.17.4': dependencies: '@cspell/cspell-types': 8.17.4 - '@cspell/cspell-pipe@8.14.4': {} - '@cspell/cspell-pipe@8.17.4': {} - '@cspell/cspell-resolver@8.14.4': - dependencies: - global-directory: 4.0.1 + '@cspell/cspell-pipe@8.18.1': {} '@cspell/cspell-resolver@8.17.4': dependencies: global-directory: 4.0.1 - '@cspell/cspell-service-bus@8.14.4': {} + '@cspell/cspell-resolver@8.18.1': + dependencies: + global-directory: 4.0.1 '@cspell/cspell-service-bus@8.17.4': {} - '@cspell/cspell-types@8.14.4': {} + '@cspell/cspell-service-bus@8.18.1': {} '@cspell/cspell-types@8.17.4': {} - '@cspell/dict-ada@4.0.2': {} + '@cspell/cspell-types@8.18.1': {} '@cspell/dict-ada@4.1.0': {} '@cspell/dict-al@1.1.0': {} - '@cspell/dict-aws@4.0.4': {} - '@cspell/dict-aws@4.0.9': {} - '@cspell/dict-bash@4.1.5': {} - '@cspell/dict-bash@4.2.0': dependencies: '@cspell/dict-shell': 1.1.0 '@cspell/dict-companies@3.1.14': {} - '@cspell/dict-companies@3.1.4': {} - - '@cspell/dict-cpp@5.1.19': {} - '@cspell/dict-cpp@6.0.3': {} - '@cspell/dict-cryptocurrencies@5.0.0': {} + '@cspell/dict-cpp@6.0.7': {} '@cspell/dict-cryptocurrencies@5.0.4': {} - '@cspell/dict-csharp@4.0.2': {} - '@cspell/dict-csharp@4.0.6': {} - '@cspell/dict-css@4.0.13': {} - '@cspell/dict-css@4.0.17': {} - '@cspell/dict-dart@2.2.1': {} - '@cspell/dict-dart@2.3.0': {} - '@cspell/dict-data-science@2.0.2': {} - '@cspell/dict-data-science@2.0.7': {} - '@cspell/dict-django@4.1.0': {} + '@cspell/dict-data-science@2.0.8': {} '@cspell/dict-django@4.1.4': {} '@cspell/dict-docker@1.1.12': {} - '@cspell/dict-docker@1.1.7': {} - - '@cspell/dict-dotnet@5.0.5': {} - '@cspell/dict-dotnet@5.0.9': {} - '@cspell/dict-elixir@4.0.3': {} - '@cspell/dict-elixir@4.0.7': {} - '@cspell/dict-en-common-misspellings@2.0.4': {} + '@cspell/dict-en-common-misspellings@2.0.10': {} '@cspell/dict-en-common-misspellings@2.0.9': {} '@cspell/dict-en-gb@1.1.33': {} - '@cspell/dict-en_us@4.3.23': {} - '@cspell/dict-en_us@4.3.31': {} + '@cspell/dict-en_us@4.4.0': {} + '@cspell/dict-filetypes@3.0.11': {} - '@cspell/dict-filetypes@3.0.4': {} - - '@cspell/dict-flutter@1.0.0': {} - '@cspell/dict-flutter@1.1.0': {} - '@cspell/dict-fonts@4.0.0': {} - '@cspell/dict-fonts@4.0.4': {} - '@cspell/dict-fsharp@1.0.1': {} - '@cspell/dict-fsharp@1.1.0': {} - '@cspell/dict-fullstack@3.2.0': {} - '@cspell/dict-fullstack@3.2.4': {} - '@cspell/dict-gaming-terms@1.0.5': {} + '@cspell/dict-fullstack@3.2.6': {} '@cspell/dict-gaming-terms@1.1.0': {} - '@cspell/dict-git@3.0.0': {} - '@cspell/dict-git@3.0.4': {} - '@cspell/dict-golang@6.0.13': {} - '@cspell/dict-golang@6.0.18': {} - '@cspell/dict-google@1.0.1': {} + '@cspell/dict-golang@6.0.20': {} '@cspell/dict-google@1.0.8': {} - '@cspell/dict-haskell@4.0.1': {} - '@cspell/dict-haskell@4.0.5': {} - '@cspell/dict-html-symbol-entities@4.0.0': {} - '@cspell/dict-html-symbol-entities@4.0.3': {} '@cspell/dict-html@4.0.11': {} - '@cspell/dict-html@4.0.6': {} - '@cspell/dict-java@5.0.11': {} - '@cspell/dict-java@5.0.7': {} - - '@cspell/dict-julia@1.0.1': {} - '@cspell/dict-julia@1.1.0': {} '@cspell/dict-k8s@1.0.10': {} - '@cspell/dict-k8s@1.0.6': {} - '@cspell/dict-kotlin@1.1.0': {} - '@cspell/dict-latex@4.0.0': {} - '@cspell/dict-latex@4.0.3': {} - '@cspell/dict-lorem-ipsum@4.0.0': {} - '@cspell/dict-lorem-ipsum@4.0.4': {} - '@cspell/dict-lua@4.0.3': {} - '@cspell/dict-lua@4.0.7': {} - '@cspell/dict-makefile@1.0.0': {} - '@cspell/dict-makefile@1.0.4': {} '@cspell/dict-markdown@2.0.9(@cspell/dict-css@4.0.17)(@cspell/dict-html-symbol-entities@4.0.3)(@cspell/dict-html@4.0.11)(@cspell/dict-typescript@3.2.0)': @@ -11617,111 +11426,86 @@ snapshots: '@cspell/dict-monkeyc@1.0.10': {} - '@cspell/dict-monkeyc@1.0.6': {} - - '@cspell/dict-node@5.0.1': {} - '@cspell/dict-node@5.0.6': {} '@cspell/dict-npm@5.1.26': {} - '@cspell/dict-npm@5.1.5': {} - - '@cspell/dict-php@4.0.10': {} + '@cspell/dict-npm@5.1.34': {} '@cspell/dict-php@4.0.14': {} - '@cspell/dict-powershell@5.0.10': {} - '@cspell/dict-powershell@5.0.14': {} '@cspell/dict-public-licenses@2.0.13': {} - '@cspell/dict-public-licenses@2.0.8': {} - '@cspell/dict-python@4.2.15': dependencies: '@cspell/dict-data-science': 2.0.7 - '@cspell/dict-python@4.2.8': + '@cspell/dict-python@4.2.17': dependencies: - '@cspell/dict-data-science': 2.0.2 - - '@cspell/dict-r@2.0.1': {} + '@cspell/dict-data-science': 2.0.8 '@cspell/dict-r@2.1.0': {} - '@cspell/dict-ruby@5.0.4': {} - '@cspell/dict-ruby@5.0.7': {} + '@cspell/dict-ruby@5.0.8': {} + '@cspell/dict-rust@4.0.11': {} - '@cspell/dict-rust@4.0.6': {} - - '@cspell/dict-scala@5.0.3': {} - '@cspell/dict-scala@5.0.7': {} '@cspell/dict-shell@1.1.0': {} - '@cspell/dict-software-terms@4.1.7': {} - '@cspell/dict-software-terms@4.2.5': {} - '@cspell/dict-sql@2.1.5': {} + '@cspell/dict-software-terms@5.0.5': {} '@cspell/dict-sql@2.2.0': {} - '@cspell/dict-svelte@1.0.2': {} - '@cspell/dict-svelte@1.0.6': {} - '@cspell/dict-swift@2.0.1': {} - '@cspell/dict-swift@2.0.5': {} - '@cspell/dict-terraform@1.0.2': {} - '@cspell/dict-terraform@1.1.0': {} - '@cspell/dict-typescript@3.1.6': {} + '@cspell/dict-terraform@1.1.1': {} '@cspell/dict-typescript@3.2.0': {} - '@cspell/dict-vue@3.0.0': {} - '@cspell/dict-vue@3.0.4': {} - '@cspell/dynamic-import@8.14.4': - dependencies: - import-meta-resolve: 4.1.0 - '@cspell/dynamic-import@8.17.4': dependencies: '@cspell/url': 8.17.4 import-meta-resolve: 4.1.0 - '@cspell/eslint-plugin@8.14.4(eslint@9.20.1(jiti@2.4.2))': + '@cspell/dynamic-import@8.18.1': dependencies: - '@cspell/cspell-types': 8.14.4 - '@cspell/url': 8.14.4 - cspell-lib: 8.14.4 - eslint: 9.20.1(jiti@2.4.2) - synckit: 0.9.2 + '@cspell/url': 8.18.1 + import-meta-resolve: 4.1.0 - '@cspell/filetypes@8.14.4': {} + '@cspell/eslint-plugin@8.18.1(eslint@9.24.0(jiti@2.4.2))': + dependencies: + '@cspell/cspell-types': 8.18.1 + '@cspell/url': 8.18.1 + cspell-lib: 8.18.1 + eslint: 9.24.0(jiti@2.4.2) + synckit: 0.10.3 '@cspell/filetypes@8.17.4': {} - '@cspell/strong-weak-map@8.14.4': {} + '@cspell/filetypes@8.18.1': {} '@cspell/strong-weak-map@8.17.4': {} - '@cspell/url@8.14.4': {} + '@cspell/strong-weak-map@8.18.1': {} '@cspell/url@8.17.4': {} + '@cspell/url@8.18.1': {} + '@csstools/color-helpers@5.0.1': {} '@csstools/css-calc@2.1.1(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)': @@ -11837,7 +11621,7 @@ snapshots: tslib: 2.8.1 optional: true - '@es-joy/jsdoccomment@0.48.0': + '@es-joy/jsdoccomment@0.49.0': dependencies: comment-parser: 1.4.1 esquery: 1.6.0 @@ -12062,19 +11846,14 @@ snapshots: '@esbuild/win32-x64@0.25.0': optional: true - '@eslint-community/eslint-utils@4.4.1(eslint@9.20.1(jiti@2.4.2))': + '@eslint-community/eslint-utils@4.5.1(eslint@9.24.0(jiti@2.4.2))': dependencies: - eslint: 9.20.1(jiti@2.4.2) - eslint-visitor-keys: 3.4.3 - - '@eslint-community/eslint-utils@4.5.1(eslint@9.20.1(jiti@2.4.2))': - dependencies: - eslint: 9.20.1(jiti@2.4.2) + eslint: 9.24.0(jiti@2.4.2) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} - '@eslint/config-array@0.19.2': + '@eslint/config-array@0.20.0': dependencies: '@eslint/object-schema': 2.1.6 debug: 4.4.0(supports-color@8.1.1) @@ -12082,15 +11861,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/core@0.11.0': - dependencies: - '@types/json-schema': 7.0.15 + '@eslint/config-helpers@0.2.1': {} '@eslint/core@0.12.0': dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.2.0': + '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 debug: 4.4.0(supports-color@8.1.1) @@ -12104,9 +11881,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.12.0': {} - - '@eslint/js@9.20.0': {} + '@eslint/js@9.24.0': {} '@eslint/object-schema@2.1.6': {} @@ -12546,6 +12321,8 @@ snapshots: '@pkgr/core@0.1.1': {} + '@pkgr/core@0.2.1': {} + '@polka/url@1.0.0-next.28': {} '@rollup/plugin-babel@5.3.1(@babel/core@7.26.9)(@types/babel__core@7.20.5)(rollup@2.79.2)': @@ -13175,15 +12952,15 @@ snapshots: '@types/node': 22.13.5 optional: true - '@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/eslint-plugin@8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.24.1 - '@typescript-eslint/type-utils': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/utils': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.24.1 - eslint: 9.20.1(jiti@2.4.2) + '@typescript-eslint/parser': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/scope-manager': 8.29.1 + '@typescript-eslint/type-utils': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.29.1 + eslint: 9.24.0(jiti@2.4.2) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -13192,14 +12969,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3)': dependencies: - '@typescript-eslint/scope-manager': 8.24.1 - '@typescript-eslint/types': 8.24.1 - '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.24.1 + '@typescript-eslint/scope-manager': 8.29.1 + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/typescript-estree': 8.29.1(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.29.1 debug: 4.4.0(supports-color@8.1.1) - eslint: 9.20.1(jiti@2.4.2) + eslint: 9.24.0(jiti@2.4.2) typescript: 5.7.3 transitivePeerDependencies: - supports-color @@ -13209,17 +12986,17 @@ snapshots: '@typescript-eslint/types': 8.24.1 '@typescript-eslint/visitor-keys': 8.24.1 - '@typescript-eslint/scope-manager@8.8.1': + '@typescript-eslint/scope-manager@8.29.1': dependencies: - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/visitor-keys': 8.8.1 + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/visitor-keys': 8.29.1 - '@typescript-eslint/type-utils@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/type-utils@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) - '@typescript-eslint/utils': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/typescript-estree': 8.29.1(typescript@5.7.3) + '@typescript-eslint/utils': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) debug: 4.4.0(supports-color@8.1.1) - eslint: 9.20.1(jiti@2.4.2) + eslint: 9.24.0(jiti@2.4.2) ts-api-utils: 2.0.1(typescript@5.7.3) typescript: 5.7.3 transitivePeerDependencies: @@ -13229,7 +13006,7 @@ snapshots: '@typescript-eslint/types@8.24.1': {} - '@typescript-eslint/types@8.8.1': {} + '@typescript-eslint/types@8.29.1': {} '@typescript-eslint/typescript-estree@7.18.0(typescript@5.7.3)': dependencies: @@ -13260,42 +13037,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.8.1(typescript@5.7.3)': + '@typescript-eslint/typescript-estree@8.29.1(typescript@5.7.3)': dependencies: - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/visitor-keys': 8.8.1 + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/visitor-keys': 8.29.1 debug: 4.4.0(supports-color@8.1.1) fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.1 - ts-api-utils: 1.3.0(typescript@5.7.3) - optionalDependencies: + ts-api-utils: 2.0.1(typescript@5.7.3) typescript: 5.7.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/utils@8.24.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.5.1(eslint@9.24.0(jiti@2.4.2)) '@typescript-eslint/scope-manager': 8.24.1 '@typescript-eslint/types': 8.24.1 '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) - eslint: 9.20.1(jiti@2.4.2) + eslint: 9.24.0(jiti@2.4.2) typescript: 5.7.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.8.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/utils@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@2.4.2)) - '@typescript-eslint/scope-manager': 8.8.1 - '@typescript-eslint/types': 8.8.1 - '@typescript-eslint/typescript-estree': 8.8.1(typescript@5.7.3) - eslint: 9.20.1(jiti@2.4.2) + '@eslint-community/eslint-utils': 4.5.1(eslint@9.24.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.29.1 + '@typescript-eslint/types': 8.29.1 + '@typescript-eslint/typescript-estree': 8.29.1(typescript@5.7.3) + eslint: 9.24.0(jiti@2.4.2) + typescript: 5.7.3 transitivePeerDependencies: - supports-color - - typescript '@typescript-eslint/visitor-keys@7.18.0': dependencies: @@ -13307,10 +13083,10 @@ snapshots: '@typescript-eslint/types': 8.24.1 eslint-visitor-keys: 4.2.0 - '@typescript-eslint/visitor-keys@8.8.1': + '@typescript-eslint/visitor-keys@8.29.1': dependencies: - '@typescript-eslint/types': 8.8.1 - eslint-visitor-keys: 3.4.3 + '@typescript-eslint/types': 8.29.1 + eslint-visitor-keys: 4.2.0 '@ungap/structured-clone@1.3.0': {} @@ -14715,24 +14491,17 @@ snapshots: crypto-random-string@2.0.0: {} - cspell-config-lib@8.14.4: - dependencies: - '@cspell/cspell-types': 8.14.4 - comment-json: 4.2.5 - yaml: 2.7.0 - cspell-config-lib@8.17.4: dependencies: '@cspell/cspell-types': 8.17.4 comment-json: 4.2.5 yaml: 2.7.0 - cspell-dictionary@8.14.4: + cspell-config-lib@8.18.1: dependencies: - '@cspell/cspell-pipe': 8.14.4 - '@cspell/cspell-types': 8.14.4 - cspell-trie-lib: 8.14.4 - fast-equals: 5.0.1 + '@cspell/cspell-types': 8.18.1 + comment-json: 4.2.5 + yaml: 2.7.0 cspell-dictionary@8.17.4: dependencies: @@ -14741,6 +14510,13 @@ snapshots: cspell-trie-lib: 8.17.4 fast-equals: 5.2.2 + cspell-dictionary@8.18.1: + dependencies: + '@cspell/cspell-pipe': 8.18.1 + '@cspell/cspell-types': 8.18.1 + cspell-trie-lib: 8.18.1 + fast-equals: 5.2.2 + cspell-gitignore@8.17.4: dependencies: '@cspell/url': 8.17.4 @@ -14748,62 +14524,35 @@ snapshots: cspell-io: 8.17.4 find-up-simple: 1.0.0 - cspell-glob@8.14.4: - dependencies: - '@cspell/url': 8.14.4 - micromatch: 4.0.8 - cspell-glob@8.17.4: dependencies: '@cspell/url': 8.17.4 micromatch: 4.0.8 - cspell-grammar@8.14.4: + cspell-glob@8.18.1: dependencies: - '@cspell/cspell-pipe': 8.14.4 - '@cspell/cspell-types': 8.14.4 + '@cspell/url': 8.18.1 + micromatch: 4.0.8 cspell-grammar@8.17.4: dependencies: '@cspell/cspell-pipe': 8.17.4 '@cspell/cspell-types': 8.17.4 - cspell-io@8.14.4: + cspell-grammar@8.18.1: dependencies: - '@cspell/cspell-service-bus': 8.14.4 - '@cspell/url': 8.14.4 + '@cspell/cspell-pipe': 8.18.1 + '@cspell/cspell-types': 8.18.1 cspell-io@8.17.4: dependencies: '@cspell/cspell-service-bus': 8.17.4 '@cspell/url': 8.17.4 - cspell-lib@8.14.4: + cspell-io@8.18.1: dependencies: - '@cspell/cspell-bundled-dicts': 8.14.4 - '@cspell/cspell-pipe': 8.14.4 - '@cspell/cspell-resolver': 8.14.4 - '@cspell/cspell-types': 8.14.4 - '@cspell/dynamic-import': 8.14.4 - '@cspell/filetypes': 8.14.4 - '@cspell/strong-weak-map': 8.14.4 - '@cspell/url': 8.14.4 - clear-module: 4.1.2 - comment-json: 4.2.5 - cspell-config-lib: 8.14.4 - cspell-dictionary: 8.14.4 - cspell-glob: 8.14.4 - cspell-grammar: 8.14.4 - cspell-io: 8.14.4 - cspell-trie-lib: 8.14.4 - env-paths: 3.0.0 - fast-equals: 5.0.1 - gensequence: 7.0.0 - import-fresh: 3.3.0 - resolve-from: 5.0.0 - vscode-languageserver-textdocument: 1.0.12 - vscode-uri: 3.0.8 - xdg-basedir: 5.1.0 + '@cspell/cspell-service-bus': 8.18.1 + '@cspell/url': 8.18.1 cspell-lib@8.17.4: dependencies: @@ -14832,11 +14581,32 @@ snapshots: vscode-uri: 3.1.0 xdg-basedir: 5.1.0 - cspell-trie-lib@8.14.4: + cspell-lib@8.18.1: dependencies: - '@cspell/cspell-pipe': 8.14.4 - '@cspell/cspell-types': 8.14.4 + '@cspell/cspell-bundled-dicts': 8.18.1 + '@cspell/cspell-pipe': 8.18.1 + '@cspell/cspell-resolver': 8.18.1 + '@cspell/cspell-types': 8.18.1 + '@cspell/dynamic-import': 8.18.1 + '@cspell/filetypes': 8.18.1 + '@cspell/strong-weak-map': 8.18.1 + '@cspell/url': 8.18.1 + clear-module: 4.1.2 + comment-json: 4.2.5 + cspell-config-lib: 8.18.1 + cspell-dictionary: 8.18.1 + cspell-glob: 8.18.1 + cspell-grammar: 8.18.1 + cspell-io: 8.18.1 + cspell-trie-lib: 8.18.1 + env-paths: 3.0.0 + fast-equals: 5.2.2 gensequence: 7.0.0 + import-fresh: 3.3.1 + resolve-from: 5.0.0 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + xdg-basedir: 5.1.0 cspell-trie-lib@8.17.4: dependencies: @@ -14844,6 +14614,12 @@ snapshots: '@cspell/cspell-types': 8.17.4 gensequence: 7.0.0 + cspell-trie-lib@8.18.1: + dependencies: + '@cspell/cspell-pipe': 8.18.1 + '@cspell/cspell-types': 8.18.1 + gensequence: 7.0.0 + cspell@8.17.4: dependencies: '@cspell/cspell-json-reporter': 8.17.4 @@ -15694,38 +15470,38 @@ snapshots: optionalDependencies: source-map: 0.6.1 - eslint-config-prettier@10.0.1(eslint@9.20.1(jiti@2.4.2)): + eslint-config-prettier@10.1.1(eslint@9.24.0(jiti@2.4.2)): dependencies: - eslint: 9.20.1(jiti@2.4.2) + eslint: 9.24.0(jiti@2.4.2) - eslint-plugin-cypress@4.1.0(eslint@9.20.1(jiti@2.4.2)): + eslint-plugin-cypress@4.2.1(eslint@9.24.0(jiti@2.4.2)): dependencies: - eslint: 9.20.1(jiti@2.4.2) + eslint: 9.24.0(jiti@2.4.2) globals: 15.15.0 eslint-plugin-html@8.1.2: dependencies: htmlparser2: 9.1.0 - eslint-plugin-jest@28.8.3(@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.5))(typescript@5.7.3): + eslint-plugin-jest@28.11.0(@typescript-eslint/eslint-plugin@8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(jest@29.7.0(@types/node@22.13.5))(typescript@5.7.3): dependencies: - '@typescript-eslint/utils': 8.8.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) - eslint: 9.20.1(jiti@2.4.2) + '@typescript-eslint/utils': 8.24.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.24.0(jiti@2.4.2) optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/eslint-plugin': 8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) jest: 29.7.0(@types/node@22.13.5) transitivePeerDependencies: - supports-color - typescript - eslint-plugin-jsdoc@50.3.2(eslint@9.20.1(jiti@2.4.2)): + eslint-plugin-jsdoc@50.6.9(eslint@9.24.0(jiti@2.4.2)): dependencies: - '@es-joy/jsdoccomment': 0.48.0 + '@es-joy/jsdoccomment': 0.49.0 are-docs-informative: 0.0.2 comment-parser: 1.4.1 debug: 4.4.0(supports-color@8.1.1) escape-string-regexp: 4.0.0 - eslint: 9.20.1(jiti@2.4.2) + eslint: 9.24.0(jiti@2.4.2) espree: 10.3.0 esquery: 1.6.0 parse-imports: 2.2.1 @@ -15740,14 +15516,14 @@ snapshots: lodash: 4.17.21 vscode-json-languageservice: 4.2.1 - eslint-plugin-lodash@8.0.0(eslint@9.20.1(jiti@2.4.2)): + eslint-plugin-lodash@8.0.0(eslint@9.24.0(jiti@2.4.2)): dependencies: - eslint: 9.20.1(jiti@2.4.2) + eslint: 9.24.0(jiti@2.4.2) lodash: 4.17.21 - eslint-plugin-markdown@5.1.0(eslint@9.20.1(jiti@2.4.2)): + eslint-plugin-markdown@5.1.0(eslint@9.24.0(jiti@2.4.2)): dependencies: - eslint: 9.20.1(jiti@2.4.2) + eslint: 9.24.0(jiti@2.4.2) mdast-util-from-markdown: 0.8.5 transitivePeerDependencies: - supports-color @@ -15759,15 +15535,15 @@ snapshots: '@microsoft/tsdoc': 0.15.1 '@microsoft/tsdoc-config': 0.17.1 - eslint-plugin-unicorn@58.0.0(eslint@9.20.1(jiti@2.4.2)): + eslint-plugin-unicorn@58.0.0(eslint@9.24.0(jiti@2.4.2)): dependencies: '@babel/helper-validator-identifier': 7.25.9 - '@eslint-community/eslint-utils': 4.5.1(eslint@9.20.1(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.5.1(eslint@9.24.0(jiti@2.4.2)) '@eslint/plugin-kit': 0.2.7 ci-info: 4.2.0 clean-regexp: 1.0.0 core-js-compat: 3.41.0 - eslint: 9.20.1(jiti@2.4.2) + eslint: 9.24.0(jiti@2.4.2) esquery: 1.6.0 globals: 16.0.0 indent-string: 5.0.0 @@ -15785,7 +15561,7 @@ snapshots: esrecurse: 4.3.0 estraverse: 4.3.0 - eslint-scope@8.2.0: + eslint-scope@8.3.0: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 @@ -15794,14 +15570,15 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.20.1(jiti@2.4.2): + eslint@9.24.0(jiti@2.4.2): dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.20.1(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.5.1(eslint@9.24.0(jiti@2.4.2)) '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.2 - '@eslint/core': 0.11.0 - '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.20.0 + '@eslint/config-array': 0.20.0 + '@eslint/config-helpers': 0.2.1 + '@eslint/core': 0.12.0 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.24.0 '@eslint/plugin-kit': 0.2.7 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 @@ -15813,7 +15590,7 @@ snapshots: cross-spawn: 7.0.6 debug: 4.4.0(supports-color@8.1.1) escape-string-regexp: 4.0.0 - eslint-scope: 8.2.0 + eslint-scope: 8.3.0 eslint-visitor-keys: 4.2.0 espree: 10.3.0 esquery: 1.6.0 @@ -16019,8 +15796,6 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-equals@5.0.1: {} - fast-equals@5.2.2: {} fast-glob@3.3.3: @@ -16280,7 +16055,7 @@ snapshots: foreground-child@3.3.0: dependencies: - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 signal-exit: 4.1.0 forever-agent@0.6.1: {} @@ -16761,11 +16536,6 @@ snapshots: ignore@7.0.3: {} - import-fresh@3.3.0: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -17063,7 +16833,7 @@ snapshots: istanbul-lib-processinfo@2.0.3: dependencies: archy: 1.0.0 - cross-spawn: 7.0.3 + cross-spawn: 7.0.6 istanbul-lib-coverage: 3.2.2 p-map: 3.0.0 rimraf: 3.0.2 @@ -19936,6 +19706,11 @@ snapshots: symbol-tree@3.2.4: {} + synckit@0.10.3: + dependencies: + '@pkgr/core': 0.2.1 + tslib: 2.8.1 + synckit@0.9.2: dependencies: '@pkgr/core': 0.1.1 @@ -20238,12 +20013,12 @@ snapshots: typescript: 5.7.3 yaml: 2.7.0 - typescript-eslint@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3): + typescript-eslint@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3))(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/parser': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/utils': 8.24.1(eslint@9.20.1(jiti@2.4.2))(typescript@5.7.3) - eslint: 9.20.1(jiti@2.4.2) + '@typescript-eslint/eslint-plugin': 8.29.1(@typescript-eslint/parser@8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.29.1(eslint@9.24.0(jiti@2.4.2))(typescript@5.7.3) + eslint: 9.24.0(jiti@2.4.2) typescript: 5.7.3 transitivePeerDependencies: - supports-color