mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-23 17:29:54 +02:00
Merge branch 'develop' into sidv/vite
* develop: Revert #3475 chore: update browsers list Support EMPTYSTR in jison parser, add unit tests for git graph parser Use undefined to mean default tagging behavior feat(git): allow cherry-pick to suppress tag altogether Update src/diagrams/git/parser/gitGraph.jison fix(git): fix cherry-pick regex parsing error test(git): add basic parsing test for cherry-pick feat(git): cherry-pick keyword supports tag attribute ci(e2e-applitols): add applitools CI action Test docs:verify Cleanup docs Fixed Linting issues #3409 Clean up dead code #3409 Fixed the truncated tags issue
This commit is contained in:
73
.github/workflows/e2e-applitools.yml
vendored
Normal file
73
.github/workflows/e2e-applitools.yml
vendored
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
name: E2E (Applitools)
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
# Because we want to limit Applitools usage, so we only want to start this
|
||||||
|
# workflow on rare occasions/manually.
|
||||||
|
inputs:
|
||||||
|
parent_branch:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
default: master
|
||||||
|
description: 'Parent branch to use for PRs'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
env:
|
||||||
|
# on PRs from forks, this secret will always be empty, for security reasons
|
||||||
|
USE_APPLI: ${{ secrets.APPLITOOLS_API_KEY && 'true' || '' }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [16.x]
|
||||||
|
steps:
|
||||||
|
- if: ${{ ! env.USE_APPLI }}
|
||||||
|
name: Warn if not using Applitools
|
||||||
|
run: |
|
||||||
|
echo "::error,title=Not using Applitols::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Setup Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
cache: yarn
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
- name: Install Yarn
|
||||||
|
run: npm i yarn --global
|
||||||
|
|
||||||
|
- name: Install Packages
|
||||||
|
run: |
|
||||||
|
yarn install --frozen-lockfile
|
||||||
|
env:
|
||||||
|
CYPRESS_CACHE_FOLDER: .cache/Cypress
|
||||||
|
|
||||||
|
- name: Run Build
|
||||||
|
run: yarn build
|
||||||
|
|
||||||
|
- if: ${{ env.USE_APPLI }}
|
||||||
|
name: Notify applitools of new batch
|
||||||
|
# Copied from docs https://applitools.com/docs/topics/integrations/github-integration-ci-setup.html
|
||||||
|
run: curl -L -d '' -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH"
|
||||||
|
env:
|
||||||
|
# e.g. mermaid-js/mermaid/my-branch
|
||||||
|
APPLITOOLS_BRANCH: ${{ github.repository }}/${{ github.ref_name }}
|
||||||
|
APPLITOOLS_PARENT_BRANCH: ${{ github.inputs.parent_branch }}
|
||||||
|
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
|
||||||
|
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'
|
||||||
|
|
||||||
|
- name: Run E2E Tests
|
||||||
|
run: yarn e2e
|
||||||
|
env:
|
||||||
|
CYPRESS_CACHE_FOLDER: .cache/Cypress
|
||||||
|
# Mermaid applitools.config.js uses this to pick batch name.
|
||||||
|
APPLI_BRANCH: ${{ github.ref_name }}
|
||||||
|
APPLITOOLS_BATCH_ID: ${{ github.sha }}
|
||||||
|
# e.g. mermaid-js/mermaid/my-branch
|
||||||
|
APPLITOOLS_BRANCH: ${{ github.repository }}/${{ github.ref_name }}
|
||||||
|
APPLITOOLS_PARENT_BRANCH: ${{ github.inputs.parent_branch }}
|
||||||
|
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
|
||||||
|
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'
|
@@ -180,7 +180,48 @@ describe('Git Graph diagram', () => {
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('11: should render a gitgraph with cherry pick commit with custom tag', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
gitGraph
|
||||||
|
commit id: "ZERO"
|
||||||
|
branch develop
|
||||||
|
commit id:"A"
|
||||||
|
checkout main
|
||||||
|
commit id:"ONE"
|
||||||
|
checkout develop
|
||||||
|
commit id:"B"
|
||||||
|
checkout main
|
||||||
|
commit id:"TWO"
|
||||||
|
cherry-pick id:"A" tag: "snapshot"
|
||||||
|
commit id:"THREE"
|
||||||
|
checkout develop
|
||||||
|
commit id:"C"
|
||||||
|
`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('11: should render a gitgraph with cherry pick commit with no tag', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
gitGraph
|
||||||
|
commit id: "ZERO"
|
||||||
|
branch develop
|
||||||
|
commit id:"A"
|
||||||
|
checkout main
|
||||||
|
commit id:"ONE"
|
||||||
|
checkout develop
|
||||||
|
commit id:"B"
|
||||||
|
checkout main
|
||||||
|
commit id:"TWO"
|
||||||
|
cherry-pick id:"A" tag: ""
|
||||||
|
commit id:"THREE"
|
||||||
|
checkout develop
|
||||||
|
commit id:"C"
|
||||||
|
`,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
});
|
||||||
it('11: should render a simple gitgraph with two cherry pick commit', () => {
|
it('11: should render a simple gitgraph with two cherry pick commit', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
@@ -207,7 +248,6 @@ describe('Git Graph diagram', () => {
|
|||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('12: should render commits for more than 8 branches', () => {
|
it('12: should render commits for more than 8 branches', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
|
@@ -30,7 +30,31 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>info below</h1>
|
<h1>info below</h1>
|
||||||
|
|
||||||
<pre class="mermaid" style="width: 100%; height: 20%">
|
<pre class="mermaid" style="width: 100%; height: 20%">
|
||||||
|
%%{init: { "logLevel": "debug", "theme": "default" , "gitGraph" : {"showBranches":"false","rotateCommitLabel":"true"},"themeVariables": {
|
||||||
|
"gitBranchLabel0": "#ff0000",
|
||||||
|
"gitBranchLabel1": "#00ff00",
|
||||||
|
"gitBranchLabel2": "#0000ff",
|
||||||
|
"git0": "#550055"
|
||||||
|
} } }%%
|
||||||
|
gitGraph
|
||||||
|
commit
|
||||||
|
branch develop
|
||||||
|
commit
|
||||||
|
commit
|
||||||
|
branch release/1.0.0
|
||||||
|
checkout release/1.0.0
|
||||||
|
commit tag:"1.0.0-beta1"
|
||||||
|
checkout develop
|
||||||
|
commit
|
||||||
|
commit
|
||||||
|
commit
|
||||||
|
commit
|
||||||
|
checkout release/1.0.0
|
||||||
|
merge develop tag: "1.0.0-beta2"
|
||||||
|
</pre>
|
||||||
|
<pre class="mermaid2" style="width: 100%; height: 20%">
|
||||||
%%{init: { "logLevel": "debug", "theme": "default" , "gitGraph" : {"showBranches":"false"},"themeVariables": {
|
%%{init: { "logLevel": "debug", "theme": "default" , "gitGraph" : {"showBranches":"false"},"themeVariables": {
|
||||||
"gitBranchLabel0": "#ff0000",
|
"gitBranchLabel0": "#ff0000",
|
||||||
"gitBranchLabel1": "#00ff00",
|
"gitBranchLabel1": "#00ff00",
|
||||||
@@ -131,6 +155,7 @@
|
|||||||
// arrowMarkerAbsolute: true,
|
// arrowMarkerAbsolute: true,
|
||||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||||
logLevel: 1,
|
logLevel: 1,
|
||||||
|
gitGraph: { rotateCommitLabel: false },
|
||||||
flowchart: { curve: 'linear', htmlLabels: true },
|
flowchart: { curve: 'linear', htmlLabels: true },
|
||||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||||
sequence: { actorMargin: 50, showSequenceNumbers: true },
|
sequence: { actorMargin: 50, showSequenceNumbers: true },
|
||||||
|
@@ -660,14 +660,27 @@ It is also possible to attach a class to a list of nodes in one statement:
|
|||||||
|
|
||||||
A shorter form of adding a class is to attach the classname to the node using the `:::` operator:
|
A shorter form of adding a class is to attach the classname to the node using the `:::` operator:
|
||||||
|
|
||||||
```mmd
|
```mermaid-example
|
||||||
|
classDiagram
|
||||||
|
class Animal:::cssClass
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
classDiagram
|
classDiagram
|
||||||
class Animal:::cssClass
|
class Animal:::cssClass
|
||||||
```
|
```
|
||||||
|
|
||||||
Or:
|
Or:
|
||||||
|
|
||||||
```mmd
|
```mermaid-example
|
||||||
|
classDiagram
|
||||||
|
class Animal:::cssClass {
|
||||||
|
-int sizeInFeet
|
||||||
|
-canEat()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
classDiagram
|
classDiagram
|
||||||
class Animal:::cssClass {
|
class Animal:::cssClass {
|
||||||
-int sizeInFeet
|
-int sizeInFeet
|
||||||
|
@@ -258,9 +258,11 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
|
|||||||
log.debug('in mergeBranch');
|
log.debug('in mergeBranch');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const cherryPick = function (sourceId, targetId) {
|
export const cherryPick = function (sourceId, targetId, tag) {
|
||||||
|
log.debug('Entering cherryPick:', sourceId, targetId, tag);
|
||||||
sourceId = common.sanitizeText(sourceId, configApi.getConfig());
|
sourceId = common.sanitizeText(sourceId, configApi.getConfig());
|
||||||
targetId = common.sanitizeText(targetId, configApi.getConfig());
|
targetId = common.sanitizeText(targetId, configApi.getConfig());
|
||||||
|
tag = common.sanitizeText(tag, configApi.getConfig());
|
||||||
|
|
||||||
if (!sourceId || typeof commits[sourceId] === 'undefined') {
|
if (!sourceId || typeof commits[sourceId] === 'undefined') {
|
||||||
let error = new Error(
|
let error = new Error(
|
||||||
@@ -328,13 +330,13 @@ export const cherryPick = function (sourceId, targetId) {
|
|||||||
parents: [head == null ? null : head.id, sourceCommit.id],
|
parents: [head == null ? null : head.id, sourceCommit.id],
|
||||||
branch: curBranch,
|
branch: curBranch,
|
||||||
type: commitType.CHERRY_PICK,
|
type: commitType.CHERRY_PICK,
|
||||||
tag: 'cherry-pick:' + sourceCommit.id,
|
tag: tag ?? 'cherry-pick:' + sourceCommit.id,
|
||||||
};
|
};
|
||||||
head = commit;
|
head = commit;
|
||||||
commits[commit.id] = commit;
|
commits[commit.id] = commit;
|
||||||
branches[curBranch] = commit.id;
|
branches[curBranch] = commit.id;
|
||||||
log.debug(branches);
|
log.debug(branches);
|
||||||
log.debug('in cheeryPick');
|
log.debug('in cherryPick');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const checkout = function (branch) {
|
export const checkout = function (branch) {
|
||||||
|
@@ -611,6 +611,54 @@ describe('when parsing a gitGraph', function () {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support cherry-picking commits', function () {
|
||||||
|
const str = `gitGraph
|
||||||
|
commit id: "ZERO"
|
||||||
|
branch develop
|
||||||
|
commit id:"A"
|
||||||
|
checkout main
|
||||||
|
cherry-pick id:"A"
|
||||||
|
`;
|
||||||
|
|
||||||
|
parser.parse(str);
|
||||||
|
const commits = parser.yy.getCommits();
|
||||||
|
const cherryPickCommitID = Object.keys(commits)[2];
|
||||||
|
expect(commits[cherryPickCommitID].tag).toBe('cherry-pick:A');
|
||||||
|
expect(commits[cherryPickCommitID].branch).toBe('main');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support cherry-picking commits with custom tag', function () {
|
||||||
|
const str = `gitGraph
|
||||||
|
commit id: "ZERO"
|
||||||
|
branch develop
|
||||||
|
commit id:"A"
|
||||||
|
checkout main
|
||||||
|
cherry-pick id:"A" tag:"MyTag"
|
||||||
|
`;
|
||||||
|
|
||||||
|
parser.parse(str);
|
||||||
|
const commits = parser.yy.getCommits();
|
||||||
|
const cherryPickCommitID = Object.keys(commits)[2];
|
||||||
|
expect(commits[cherryPickCommitID].tag).toBe('MyTag');
|
||||||
|
expect(commits[cherryPickCommitID].branch).toBe('main');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support cherry-picking commits with no tag', function () {
|
||||||
|
const str = `gitGraph
|
||||||
|
commit id: "ZERO"
|
||||||
|
branch develop
|
||||||
|
commit id:"A"
|
||||||
|
checkout main
|
||||||
|
cherry-pick id:"A" tag:""
|
||||||
|
`;
|
||||||
|
|
||||||
|
parser.parse(str);
|
||||||
|
const commits = parser.yy.getCommits();
|
||||||
|
const cherryPickCommitID = Object.keys(commits)[2];
|
||||||
|
expect(commits[cherryPickCommitID].tag).toBe('');
|
||||||
|
expect(commits[cherryPickCommitID].branch).toBe('main');
|
||||||
|
});
|
||||||
|
|
||||||
it('should throw error when try to branch existing branch: main', function () {
|
it('should throw error when try to branch existing branch: main', function () {
|
||||||
const str = `gitGraph
|
const str = `gitGraph
|
||||||
commit
|
commit
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
import { select } from 'd3';
|
import { select } from 'd3';
|
||||||
import { configureSvgSize } from '../../setupGraphViewbox';
|
import { getConfig, setupGraphViewbox } from '../../diagram-api/diagramAPI';
|
||||||
import { log } from '../../logger';
|
import { log } from '../../logger';
|
||||||
import { getConfig } from '../../config';
|
|
||||||
import addSVGAccessibilityFields from '../../accessibility';
|
import addSVGAccessibilityFields from '../../accessibility';
|
||||||
|
|
||||||
let allCommitsDict = {};
|
let allCommitsDict = {};
|
||||||
@@ -523,18 +522,8 @@ export const draw = function (txt, id, ver, diagObj) {
|
|||||||
drawArrows(diagram, allCommitsDict);
|
drawArrows(diagram, allCommitsDict);
|
||||||
drawCommits(diagram, allCommitsDict, true);
|
drawCommits(diagram, allCommitsDict, true);
|
||||||
|
|
||||||
const padding = gitGraphConfig.diagramPadding;
|
// Setup the view box and size of the svg element
|
||||||
const svgBounds = diagram.node().getBBox();
|
setupGraphViewbox(undefined, diagram, gitGraphConfig.diagramPadding, conf.useMaxWidth);
|
||||||
const width = svgBounds.width + padding * 2;
|
|
||||||
const height = svgBounds.height + padding * 2;
|
|
||||||
|
|
||||||
configureSvgSize(diagram, height, width, conf.useMaxWidth);
|
|
||||||
const vBox = `${
|
|
||||||
svgBounds.x -
|
|
||||||
padding -
|
|
||||||
(gitGraphConfig.showBranches && gitGraphConfig.rotateCommitLabel === true ? 30 : 0)
|
|
||||||
} ${svgBounds.y - padding} ${width} ${height}`;
|
|
||||||
diagram.attr('viewBox', vBox);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@@ -47,7 +47,7 @@ commit(?=\s|$) return 'COMMIT';
|
|||||||
branch(?=\s|$) return 'BRANCH';
|
branch(?=\s|$) return 'BRANCH';
|
||||||
"order:" return 'ORDER';
|
"order:" return 'ORDER';
|
||||||
merge(?=\s|$) return 'MERGE';
|
merge(?=\s|$) return 'MERGE';
|
||||||
cherry-pick(?=\s|$) return 'CHERRY_PICK';
|
cherry\-pick(?=\s|$) return 'CHERRY_PICK';
|
||||||
// "reset" return 'RESET';
|
// "reset" return 'RESET';
|
||||||
checkout(?=\s|$) return 'CHECKOUT';
|
checkout(?=\s|$) return 'CHECKOUT';
|
||||||
"LR" return 'DIR';
|
"LR" return 'DIR';
|
||||||
@@ -57,6 +57,7 @@ checkout(?=\s|$) return 'CHECKOUT';
|
|||||||
"options"\r?\n this.begin("options"); //
|
"options"\r?\n this.begin("options"); //
|
||||||
<options>[ \r\n\t]+"end" this.popState(); // not used anymore in the renderer, fixed for backward compatibility
|
<options>[ \r\n\t]+"end" this.popState(); // not used anymore in the renderer, fixed for backward compatibility
|
||||||
<options>[\s\S]+(?=[ \r\n\t]+"end") return 'OPT'; //
|
<options>[\s\S]+(?=[ \r\n\t]+"end") return 'OPT'; //
|
||||||
|
["]["] return 'EMPTYSTR';
|
||||||
["] this.begin("string");
|
["] this.begin("string");
|
||||||
<string>["] this.popState();
|
<string>["] this.popState();
|
||||||
<string>[^"]* return 'STR';
|
<string>[^"]* return 'STR';
|
||||||
@@ -117,7 +118,11 @@ branchStatement
|
|||||||
;
|
;
|
||||||
|
|
||||||
cherryPickStatement
|
cherryPickStatement
|
||||||
: CHERRY_PICK COMMIT_ID STR {yy.cherryPick($3)}
|
: CHERRY_PICK COMMIT_ID STR {yy.cherryPick($3, '', undefined)}
|
||||||
|
| CHERRY_PICK COMMIT_ID STR COMMIT_TAG STR {yy.cherryPick($3, '', $5)}
|
||||||
|
| CHERRY_PICK COMMIT_ID STR COMMIT_TAG EMPTYSTR {yy.cherryPick($3, '', '')}
|
||||||
|
| CHERRY_PICK COMMIT_TAG STR COMMIT_ID STR {yy.cherryPick($5, '', $3)}
|
||||||
|
| CHERRY_PICK COMMIT_TAG EMPTYSTR COMMIT_ID STR {yy.cherryPick($3, '', '')}
|
||||||
;
|
;
|
||||||
|
|
||||||
mergeStatement
|
mergeStatement
|
||||||
|
@@ -493,14 +493,14 @@ It is also possible to attach a class to a list of nodes in one statement:
|
|||||||
|
|
||||||
A shorter form of adding a class is to attach the classname to the node using the `:::` operator:
|
A shorter form of adding a class is to attach the classname to the node using the `:::` operator:
|
||||||
|
|
||||||
```mmd
|
```mermaid-example
|
||||||
classDiagram
|
classDiagram
|
||||||
class Animal:::cssClass
|
class Animal:::cssClass
|
||||||
```
|
```
|
||||||
|
|
||||||
Or:
|
Or:
|
||||||
|
|
||||||
```mmd
|
```mermaid-example
|
||||||
classDiagram
|
classDiagram
|
||||||
class Animal:::cssClass {
|
class Animal:::cssClass {
|
||||||
-int sizeInFeet
|
-int sizeInFeet
|
||||||
|
13
yarn.lock
13
yarn.lock
@@ -4087,15 +4087,10 @@ camelcase@^6.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
|
||||||
integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
|
integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001359:
|
caniuse-lite@^1.0.30001359, caniuse-lite@^1.0.30001400:
|
||||||
version "1.0.30001397"
|
version "1.0.30001406"
|
||||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001397.tgz"
|
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001406.tgz"
|
||||||
integrity sha512-SW9N2TbCdLf0eiNDRrrQXx2sOkaakNZbCjgNpPyMJJbiOrU5QzMIrXOVMRM1myBXTD5iTkdrtU/EguCrBocHlA==
|
integrity sha512-bWTlaXUy/rq0BBtYShc/jArYfBPjEV95euvZ8JVtO43oQExEN/WquoqpufFjNu4kSpi5cy5kMbNvzztWDfv1Jg==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001400:
|
|
||||||
version "1.0.30001402"
|
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001402.tgz#aa29e1f47f5055b0d0c07696a67b8b08023d14c8"
|
|
||||||
integrity sha512-Mx4MlhXO5NwuvXGgVb+hg65HZ+bhUYsz8QtDGDo2QmaJS2GBX47Xfi2koL86lc8K+l+htXeTEB/Aeqvezoo6Ew==
|
|
||||||
|
|
||||||
capture-exit@^2.0.0:
|
capture-exit@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
|
Reference in New Issue
Block a user