diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..a1aed17d7 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,18 @@ +{ + "env": { + "browser": true, + "es6": true + }, + "parserOptions": { + "ecmaFeatures": { + "experimentalObjectRestSpread": true, + "jsx": true + }, + "sourceType": "module" + }, + "extends": ["prettier"], + "plugins": ["prettier"], + "rules": { + "prettier/prettier": ["error"] + } +} diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dd84ea782..3ee68b30b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,7 +2,7 @@ name: Bug report about: Create a report to help us improve title: '' -labels: '' +labels: 'Status: Triage, Type: Bug / Error' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md deleted file mode 100644 index 48d5f81fa..000000000 --- a/.github/ISSUE_TEMPLATE/custom.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Custom issue template -about: Describe this issue template's purpose here. -title: '' -labels: '' -assignees: '' - ---- - - diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index bbcbbe7d6..f79a30928 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: Feature request about: Suggest an idea for this project title: '' -labels: '' +labels: 'Status: Triage, Type: Enhancement' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 000000000..4f7444aa8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,15 @@ +--- +name: Question +about: Get some help from the community. +title: '' +labels: 'Help wanted!, Type: Other' +assignees: '' + +--- + +## Help us help you! +You want an answer. Here are some ways to get it quicker: +* Use a clear and concise title. +* Try to pose a clear and concise question. +* Include as much, or as little, code as necessary. +* Don't be shy to give us some screenshots, if it helps! diff --git a/.github/stale.yml b/.github/stale.yml index bd380cfc0..761f26cb9 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,14 +1,12 @@ # Number of days of inactivity before an issue becomes stale daysUntilStale: 60 # Number of days of inactivity before a stale issue is closed -daysUntilClose: 7 +daysUntilClose: 14 # Issues with these labels will never be considered stale exemptLabels: - - Status: Pinned - - Area: Security - - pinned + - Retained # Label to use when marking an issue as stale -staleLabel: Status: Wontfix +staleLabel: Inactive # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had @@ -16,4 +14,6 @@ markComment: > for your contributions. If you are still interested in this issue and it is still relevant you can comment to revive it. # Comment to post when closing a stale issue. Set to `false` to disable -closeComment: false +closeComment: > + This issue has been been automatically closed due to a lack of activity. + This is done to maintain a clean list of issues that the community is interested in developing. diff --git a/.github/workflows/issue-triage.yml b/.github/workflows/issue-triage.yml new file mode 100644 index 000000000..53d5f6b87 --- /dev/null +++ b/.github/workflows/issue-triage.yml @@ -0,0 +1,14 @@ +name: Apply triage label to new issue + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: andymckay/labeler@1.0 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + labels: "Status: Triage" diff --git a/.github/workflows/lock-closed-issue.yml b/.github/workflows/lock-closed-issue.yml new file mode 100644 index 000000000..ae74c03ef --- /dev/null +++ b/.github/workflows/lock-closed-issue.yml @@ -0,0 +1,13 @@ +name: Lock closed issue + +on: + issues: + types: [closed] + +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: Dunning-Kruger/lock-issues@v1 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/unlock-reopened-issues.yml b/.github/workflows/unlock-reopened-issues.yml new file mode 100644 index 000000000..09469ed8b --- /dev/null +++ b/.github/workflows/unlock-reopened-issues.yml @@ -0,0 +1,13 @@ +name: Unlock reopened issue + +on: + issues: + types: [reopened] + +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: Dunning-Kruger/unlock-issues@v1 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.gitignore b/.gitignore index afceb98c0..74ecd58ff 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ node_modules/ coverage/ +.idea/ dist/*.js dist/*.map diff --git a/.percy.yml b/.percy.yml new file mode 100644 index 000000000..5499b41f2 --- /dev/null +++ b/.percy.yml @@ -0,0 +1,3 @@ +version: 1 +snapshot: + widths: [1280] \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..5ac85e271 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "printWidth": 100, + "singleQuote": true +} diff --git a/.tern-project b/.tern-project new file mode 100644 index 000000000..cf9751411 --- /dev/null +++ b/.tern-project @@ -0,0 +1,22 @@ +{ + "ecmaVersion": 6, + "libs": [ + "browser" + ], + "loadEagerly": [ + "path/to/your/js/**/*.js" + ], + "dontLoad": [ + "node_modules/**", + "path/to/your/js/**/*.js" + ], + "plugins": { + "modules": {}, + "es_modules": {}, + "node": {}, + "doc_comment": { + "fullDocs": true, + "strong": true + } + } +} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index d28528ef6..98c9666a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,12 @@ dist: trusty language: node_js node_js: - - "8" + - "10" +cache: + npm: false script: + - yarn build - yarn test --coverage + - yarn e2e after_success: - cat ./coverage/lcov.info | ./node_modules/.bin/coveralls diff --git a/README.md b/README.md index 5f852228b..b7372ce37 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ [![Build Status](https://travis-ci.org/knsv/mermaid.svg?branch=master)](https://travis-ci.org/knsv/mermaid) [![Coverage Status](https://coveralls.io/repos/github/knsv/mermaid/badge.svg?branch=master)](https://coveralls.io/github/knsv/mermaid?branch=master) [![Join the chat at https://gitter.im/knsv/mermaid](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/knsv/mermaid?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/Mermaid/mermaid) # mermaid @@ -9,16 +10,16 @@ In version 8.2 a security improvement was introduced. A securityLevel configuration was introduced which sets the level of trust to be used on the parsed diagrams. * **`strict`**: (default) tags in text are encoded, click functionality is disabled -* `loose`: tags in text are allowed, click functionality is enabledClosed issues: +* `loose`: tags in text are allowed, click functionality is enabled ⚠️ **Note** : This changes the default behaviour of mermaid so that after upgrade to 8.2, if the securityLevel is not configured, tags in flowcharts are encoded as tags and clicking is prohibited. -If your application is taking resposibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed. +If your application is taking responsibility for the diagram source security you can set the securityLevel accordingly. By doing this clicks and tags are again allowed. ```javascript - mermaidAPI.initialize({ - securityLevel: 'loose' - }); +mermaidAPI.initialize({ + securityLevel: 'loose' +}); ``` **🖖 Keep a steady pulse: mermaid needs more Collaborators [#866](https://github.com/knsv/mermaid/issues/866)** @@ -31,7 +32,7 @@ Ever wanted to simplify documentation and avoid heavy tools like Visio when expl This is why mermaid was born, a simple markdown-like script language for generating charts from text via javascript. -**Mermaid was nomiated and won the JS Open Source Awards (2019) in the category _The most exciting use of technology_!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** +**Mermaid was nominated and won the JS Open Source Awards (2019) in the category _The most exciting use of technology_!!! Thanks to all involved, people committing pull requests, people answering questions and special thanks to Tyler Long who is helping me maintain the project.** ### Flowchart @@ -75,7 +76,7 @@ section A section Completed task :done, des1, 2014-01-06,2014-01-08 Active task :active, des2, 2014-01-09, 3d Future task : des3, after des2, 5d -Future task2 : des4, after des3, 5d +Future task2 : des4, after des3, 5d ``` ![Gantt diagram](./img/gantt.png) @@ -85,6 +86,7 @@ Future task2 : des4, after des3, 5d ``` classDiagram Class01 <|-- AveryLongClass : Cool +<> Class01 Class03 *-- Class04 Class05 o-- Class06 Class07 .. Class08 @@ -97,6 +99,11 @@ Class01 : size() Class01 : int chimp Class01 : int gorilla Class08 <--> C2: Cool label +class Class10 { + <> + int id + size() +} ``` ![Class diagram](./img/class.png) @@ -130,9 +137,7 @@ merge newbranch ### CDN -``` -https://unpkg.com/mermaid@/dist/ -``` + https://unpkg.com/mermaid@/dist/ Replace `` with expected version number. @@ -140,9 +145,7 @@ Example: https://unpkg.com/mermaid@7.1.0/dist/ ### Node.js -``` -yarn add mermaid -``` + yarn add mermaid ## Documentation @@ -190,8 +193,8 @@ Don't hesitate to contact me if you want to get involved. yarn lint -We use [JavaScript Standard Style](https://github.com/feross/standard). -We recommend you installing [editor plugins](https://github.com/feross/standard#are-there-text-editor-plugins) so you can get real time lint result. +We use [eslint](https://eslint.org/). +We recommend you installing [editor plugins](https://eslint.org/docs/user-guide/integrations) so you can get real time lint result. ## Test diff --git a/cypress.json b/cypress.json new file mode 100644 index 000000000..a56d1ac68 --- /dev/null +++ b/cypress.json @@ -0,0 +1 @@ +{ "video": false } diff --git a/cypress/examples/actions.spec.js b/cypress/examples/actions.spec.js new file mode 100644 index 000000000..20e12cc6d --- /dev/null +++ b/cypress/examples/actions.spec.js @@ -0,0 +1,272 @@ +/// + +context('Actions', () => { + beforeEach(() => { + cy.visit('https://example.cypress.io/commands/actions') + }) + + // https://on.cypress.io/interacting-with-elements + + it('.type() - type into a DOM element', () => { + // https://on.cypress.io/type + cy.get('.action-email') + .type('fake@email.com').should('have.value', 'fake@email.com') + + // .type() with special character sequences + .type('{leftarrow}{rightarrow}{uparrow}{downarrow}') + .type('{del}{selectall}{backspace}') + + // .type() with key modifiers + .type('{alt}{option}') //these are equivalent + .type('{ctrl}{control}') //these are equivalent + .type('{meta}{command}{cmd}') //these are equivalent + .type('{shift}') + + // Delay each keypress by 0.1 sec + .type('slow.typing@email.com', { delay: 100 }) + .should('have.value', 'slow.typing@email.com') + + cy.get('.action-disabled') + // Ignore error checking prior to type + // like whether the input is visible or disabled + .type('disabled error checking', { force: true }) + .should('have.value', 'disabled error checking') + }) + + it('.focus() - focus on a DOM element', () => { + // https://on.cypress.io/focus + cy.get('.action-focus').focus() + .should('have.class', 'focus') + .prev().should('have.attr', 'style', 'color: orange;') + }) + + it('.blur() - blur off a DOM element', () => { + // https://on.cypress.io/blur + cy.get('.action-blur').type('About to blur').blur() + .should('have.class', 'error') + .prev().should('have.attr', 'style', 'color: red;') + }) + + it('.clear() - clears an input or textarea element', () => { + // https://on.cypress.io/clear + cy.get('.action-clear').type('Clear this text') + .should('have.value', 'Clear this text') + .clear() + .should('have.value', '') + }) + + it('.submit() - submit a form', () => { + // https://on.cypress.io/submit + cy.get('.action-form') + .find('[type="text"]').type('HALFOFF') + cy.get('.action-form').submit() + .next().should('contain', 'Your form has been submitted!') + }) + + it('.click() - click on a DOM element', () => { + // https://on.cypress.io/click + cy.get('.action-btn').click() + + // You can click on 9 specific positions of an element: + // ----------------------------------- + // | topLeft top topRight | + // | | + // | | + // | | + // | left center right | + // | | + // | | + // | | + // | bottomLeft bottom bottomRight | + // ----------------------------------- + + // clicking in the center of the element is the default + cy.get('#action-canvas').click() + + cy.get('#action-canvas').click('topLeft') + cy.get('#action-canvas').click('top') + cy.get('#action-canvas').click('topRight') + cy.get('#action-canvas').click('left') + cy.get('#action-canvas').click('right') + cy.get('#action-canvas').click('bottomLeft') + cy.get('#action-canvas').click('bottom') + cy.get('#action-canvas').click('bottomRight') + + // .click() accepts an x and y coordinate + // that controls where the click occurs :) + + cy.get('#action-canvas') + .click(80, 75) // click 80px on x coord and 75px on y coord + .click(170, 75) + .click(80, 165) + .click(100, 185) + .click(125, 190) + .click(150, 185) + .click(170, 165) + + // click multiple elements by passing multiple: true + cy.get('.action-labels>.label').click({ multiple: true }) + + // Ignore error checking prior to clicking + cy.get('.action-opacity>.btn').click({ force: true }) + }) + + it('.dblclick() - double click on a DOM element', () => { + // https://on.cypress.io/dblclick + + // Our app has a listener on 'dblclick' event in our 'scripts.js' + // that hides the div and shows an input on double click + cy.get('.action-div').dblclick().should('not.be.visible') + cy.get('.action-input-hidden').should('be.visible') + }) + + it('.check() - check a checkbox or radio element', () => { + // https://on.cypress.io/check + + // By default, .check() will check all + // matching checkbox or radio elements in succession, one after another + cy.get('.action-checkboxes [type="checkbox"]').not('[disabled]') + .check().should('be.checked') + + cy.get('.action-radios [type="radio"]').not('[disabled]') + .check().should('be.checked') + + // .check() accepts a value argument + cy.get('.action-radios [type="radio"]') + .check('radio1').should('be.checked') + + // .check() accepts an array of values + cy.get('.action-multiple-checkboxes [type="checkbox"]') + .check(['checkbox1', 'checkbox2']).should('be.checked') + + // Ignore error checking prior to checking + cy.get('.action-checkboxes [disabled]') + .check({ force: true }).should('be.checked') + + cy.get('.action-radios [type="radio"]') + .check('radio3', { force: true }).should('be.checked') + }) + + it('.uncheck() - uncheck a checkbox element', () => { + // https://on.cypress.io/uncheck + + // By default, .uncheck() will uncheck all matching + // checkbox elements in succession, one after another + cy.get('.action-check [type="checkbox"]') + .not('[disabled]') + .uncheck().should('not.be.checked') + + // .uncheck() accepts a value argument + cy.get('.action-check [type="checkbox"]') + .check('checkbox1') + .uncheck('checkbox1').should('not.be.checked') + + // .uncheck() accepts an array of values + cy.get('.action-check [type="checkbox"]') + .check(['checkbox1', 'checkbox3']) + .uncheck(['checkbox1', 'checkbox3']).should('not.be.checked') + + // Ignore error checking prior to unchecking + cy.get('.action-check [disabled]') + .uncheck({ force: true }).should('not.be.checked') + }) + + it('.select() - select an option in a