From dc9c866041d9ab2ba4bd76d3a250eb1fe99e35ac Mon Sep 17 00:00:00 2001 From: Rodrigo Fernandes Date: Sun, 29 Dec 2019 22:31:32 +0000 Subject: [PATCH] clean: Improve build configurations --- .eslintignore | 10 - .eslintrc.js | 58 + .eslintrc.json | 30 - .github/ISSUE_TEMPLATE.md | 44 +- .github/ISSUE_TEMPLATE/bug_report.md | 31 +- .github/ISSUE_TEMPLATE/feature_request.md | 22 +- .github/workflows/ci.yml | 10 +- .github/workflows/release.yml | 8 +- .github/workflows/website.yml | 18 +- .gitignore | 4 +- .prettierrc.json | 17 + .vscode/settings.json | 4 +- CODE_OF_CONDUCT.md | 81 +- CONTRIBUTING.md | 49 +- CREDITS.md | 9 +- LICENSE.md | 26 +- README.md | 243 ++-- SECURITY.md | 33 +- jest.config.js | 25 +- package.json | 87 +- postcss.config.js | 10 + scripts/hulk.ts | 90 +- src/__tests__/diff-parser-tests.ts | 572 ++++----- src/__tests__/diff2html-tests.ts | 150 +-- src/__tests__/file-list-printer-tests.ts | 78 +- src/__tests__/hogan-cache-tests.ts | 65 +- src/__tests__/line-by-line-tests.ts | 206 ++-- src/__tests__/printer-utils-tests.ts | 165 ++- src/__tests__/side-by-side-printer-tests.ts | 134 +-- src/__tests__/utils-tests.ts | 36 +- src/diff-parser.ts | 64 +- src/diff2html.ts | 20 +- src/file-list-renderer.ts | 28 +- src/hoganjs-utils.ts | 6 +- src/line-by-line-renderer.ts | 108 +- src/rematch.ts | 8 +- src/render-utils.ts | 88 +- src/side-by-side-renderer.ts | 112 +- src/types.ts | 20 +- src/ui/css/diff2html.css | 4 +- src/ui/js/diff2html-ui-base.ts | 228 ++++ src/ui/js/diff2html-ui-slim.ts | 12 + src/ui/js/diff2html-ui.ts | 225 +--- ...s-internals.ts => highlight.js-helpers.ts} | 34 +- src/ui/js/highlight.js-interface.ts | 69 ++ src/ui/js/highlight.js-slim.ts | 203 ++++ src/utils.ts | 38 +- typings/merge.d.ts | 2 +- webpack.bundles.ts | 89 +- webpack.website.ts | 138 +-- website/main.css | 140 ++- website/main.ts | 2 +- website/templates/helpers/block.ts | 4 +- website/templates/helpers/partial.ts | 2 +- website/templates/pages/demo/demo.css | 1 - website/templates/pages/demo/demo.ts | 128 +- website/templates/pages/index/index.css | 176 +-- website/templates/pages/index/index.ts | 10 +- yarn.lock | 1031 +++++++++++------ 59 files changed, 2980 insertions(+), 2325 deletions(-) delete mode 100644 .eslintignore create mode 100644 .eslintrc.js delete mode 100644 .eslintrc.json create mode 100644 .prettierrc.json create mode 100644 postcss.config.js create mode 100644 src/ui/js/diff2html-ui-base.ts create mode 100644 src/ui/js/diff2html-ui-slim.ts rename src/ui/js/{highlight.js-internals.ts => highlight.js-helpers.ts} (85%) create mode 100644 src/ui/js/highlight.js-interface.ts create mode 100644 src/ui/js/highlight.js-slim.ts delete mode 100644 website/templates/pages/demo/demo.css diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 35da219..0000000 --- a/.eslintignore +++ /dev/null @@ -1,10 +0,0 @@ -# Skip build results -_target/** -coverage/** -bundles/** -docs/** -lib/** -lib-esm/** -node_modules/** -src/diff2html-templates.* -typings/** diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..3015a69 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,58 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 2018, + sourceType: 'module', + }, + env: { + browser: true, + es6: true, + node: true, + }, + globals: { + Atomics: 'readonly', + SharedArrayBuffer: 'readonly', + document: 'readonly', + navigator: 'readonly', + window: 'readonly', + }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:json/recommended', + 'plugin:promise/recommended', + 'plugin:import/errors', + 'plugin:import/warnings', + 'plugin:import/typescript', + 'plugin:node/recommended', + 'plugin:sonarjs/recommended', + 'plugin:jest/recommended', + 'plugin:jest/style', + 'prettier', + 'prettier/@typescript-eslint', + 'prettier/babel', + ], + plugins: ['@typescript-eslint', 'json', 'promise', 'import', 'node', 'sonarjs', 'jest', 'optimize-regex'], + rules: { + // Enable + 'optimize-regex/optimize-regex': 'error', + // Hack: For some reason we need pass again the extensions + 'node/no-missing-import': [ + 'error', + { + tryExtensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], + }, + ], + // Disable + // https://github.com/benmosher/eslint-plugin-import/issues/1446 + 'import/named': 'off', + // We don't need this since we are using transpilation + 'node/no-unsupported-features/es-syntax': 'off', + 'no-process-exit': 'off', + // Too verbose + 'sonarjs/no-duplicate-string': 'off', + // Too verbose + 'sonarjs/cognitive-complexity': 'off', + }, +}; diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index a20ab3b..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 2018, - "sourceType": "module", - "ecmaFeatures": { - "experimentalObjectRestSpread": true, - "jsx": true - } - }, - "env": { - "es6": true, - "node": true, - "browser": true, - "commonjs": true - }, - "plugins": ["standard", "node", "import", "promise", "@typescript-eslint", "jest"], - "globals": { - "document": false, - "navigator": false, - "window": false - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:jest/recommended", - "plugin:promise/recommended", - "standard", - "plugin:prettier/recommended" - ] -} diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 34e2a12..1acfd0e 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,44 +1,44 @@ ### Step -1: Before filling an issue check out troubleshooting section - * Go to [README.md#Troubleshooting](https://github.com/rtfpessoa/diff2html#troubleshooting) +- Go to [README.md#Troubleshooting](https://github.com/rtfpessoa/diff2html#troubleshooting) ### Step 0: Describe your environment - * OS: _____ - * diff2html version: _____ - * Using diff2html directly or using diff2html-ui helper: _____ - * Extra flags: _____ +- OS: **\_** +- diff2html version: **\_** +- Using diff2html directly or using diff2html-ui helper: **\_** +- Extra flags: **\_** ### Step 1: Describe the problem: #### Steps to reproduce: - 1. _____ - 2. _____ - 3. _____ +1. *** +2. *** +3. *** #### diff example: - ```diff - diff --git describe.c - index fabadb8,cc95eb0..4866510 - --- a/describe.c - +++ b/describe.c - @@@ -98,20 -98,12 +98,20 @@@ - return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1; - } - ``` +```diff +diff --git describe.c +index fabadb8,cc95eb0..4866510 +--- a/describe.c ++++ b/describe.c +@@@ -98,20 -98,12 +98,20 @@@ + return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1; + } +``` #### Observed Results: - * What happened? This could be a description, log output, etc. +- What happened? This could be a description, log output, etc. #### Expected Results: - * What did you expect to happen? +- What did you expect to happen? #### Relevant Code: - ``` - // TODO(you): code here to reproduce the problem - ``` +``` +// TODO(you): code here to reproduce the problem +``` diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 4b12df1..9cccf52 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,32 +1,23 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - --- -**Describe the bug** -A clear and concise description of what the bug is. +name: Bug report about: Create a report to help us improve title: "" labels: "" assignees: "" ---**Describe the bug** A +clear and concise description of what the bug is. + +**To Reproduce** Steps to reproduce the behavior: -**To Reproduce** -Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error -**Expected behavior** -A clear and concise description of what you expected to happen. +**Expected behavior** A clear and concise description of what you expected to happen. -**Screenshots** -If applicable, add screenshots to help explain your problem. +**Screenshots** If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - - OS: [e.g. Windows, Linux, Mac] - - Browser [e.g. Firefox, Chrome, Safari] - - Version [e.g. 22] -**Additional context** -Add any other context about the problem here. +- OS: [e.g. Windows, Linux, Mac] +- Browser [e.g. Firefox, Chrome, Safari] +- Version [e.g. 22] + +**Additional context** Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index bbcbbe7..3e63506 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,20 +1,12 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - --- -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] +name: Feature request about: Suggest an idea for this project title: "" labels: "" assignees: "" ---**Is your feature +request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always +frustrated when [...] -**Describe the solution you'd like** -A clear and concise description of what you want to happen. +**Describe the solution you'd like** A clear and concise description of what you want to happen. -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. +**Describe alternatives you've considered** A clear and concise description of any alternative solutions or features +you've considered. -**Additional context** -Add any other context or screenshots about the feature request here. +**Additional context** Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89281cf..50b99ca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,17 +31,13 @@ jobs: ${{ runner.os }}-yarn- - name: Install dependencies run: yarn install - - name: Lint - run: yarn run lint - - name: Build - run: yarn run build - - name: Test - run: yarn run coverage + - name: Validate + run: yarn run validate - name: Push coverage to Codacy if: matrix.node-version == '13.x' env: CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} - run: yarn run codacy + run: yarn run coverage:push - name: Save coverage report if: matrix.node-version == '13.x' uses: actions/upload-artifact@v1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c8ba8dc..5b94b1b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,8 @@ name: Release on: - push: + pull_request: + types: [closed] branches: - master @@ -12,6 +13,7 @@ jobs: image: codacy/git-version steps: - uses: actions/checkout@v1 + if: github.event.pull_request.merged - name: Configure Git run: | git checkout -f "${GITHUB_REF#refs/heads/}" @@ -46,7 +48,7 @@ jobs: path: tag.txt publish: - needs: [version, build] + needs: [version] runs-on: ubuntu-18.04 env: CI: true @@ -84,7 +86,7 @@ jobs: git config user.email "$GITHUB_ACTOR@users.noreply.github.com" git config user.name "$GITHUB_ACTOR" - name: Install dependencies - run: yarn install + run: yarn - name: Prepare version env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index b950edb..f2f8c35 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -1,7 +1,8 @@ name: Website on: - push: + pull_request: + types: [closed] branches: - master @@ -15,6 +16,7 @@ jobs: node-version: [13.x] steps: - uses: actions/checkout@v1 + if: github.event.pull_request.merged - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v1 with: @@ -31,13 +33,11 @@ jobs: restore-keys: | ${{ runner.os }}-yarn- - name: Install dependencies - run: yarn install - - name: Lint - run: yarn run lint - - name: Build - run: yarn run build - - name: Test - run: yarn run coverage + run: yarn + - name: Build website + run: | + yarn run build:templates + yarn run build:website - name: Save website artifact if: matrix.node-version == '13.x' uses: actions/upload-artifact@v1 @@ -59,5 +59,5 @@ jobs: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} run: | - cd docs + cd website aws s3 sync . s3://diff2html.xyz --region eu-west-1 diff --git a/.gitignore b/.gitignore index f389625..05f9eb6 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,7 @@ node_modules/ npm-debug.log yarn-error.log -# Istanbul +# Coverage coverage/ # Bower @@ -29,7 +29,7 @@ bower_components/ # Terraform /terraform/.terraform -/_target +/_target/ /src/diff2html-templates.* /docs/ /bundles/ diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..9b887a9 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,17 @@ +{ + "arrowParens": "avoid", + "bracketSpacing": true, + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxBracketSameLine": false, + "jsxSingleQuote": false, + "printWidth": 120, + "proseWrap": "always", + "quoteProps": "as-needed", + "requirePragma": false, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all", + "useTabs": false +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 55712c1..25fa621 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "typescript.tsdk": "node_modules/typescript/lib" -} \ No newline at end of file + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index e0e6195..c995da3 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -2,75 +2,60 @@ ## Our Pledge -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, sex characteristics, gender identity and expression, -level of experience, education, socio-economic status, nationality, personal -appearance, race, religion, or sexual identity and orientation. +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making +participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, +disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, +socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards -Examples of behavior that contributes to creating a positive environment -include: +Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting +- The use of sexualized language or imagery and unwelcome sexual attention or advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take +appropriate and fair corrective action in response to any instances of unacceptable behavior. -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, +issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any +contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the +project or its community. Examples of representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed representative at an online or offline +event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at rtfrodrigo [at] gmail [dot] com. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at +rtfrodrigo [at] gmail [dot] com. All complaints will be reviewed and investigated and will result in a response that is +deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with +regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent +repercussions as determined by other members of the project's leadership. ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at +https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org -For answers to common questions about this code of conduct, see -https://www.contributor-covenant.org/faq +For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8427681..809f3d5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,31 +2,33 @@ ### Main rules -* Before you open a ticket or send a pull request, [search](https://github.com/rtfpessoa/diff2html/issues) for previous discussions about the same feature or issue. Add to the earlier ticket if you find one. +- Before you open a ticket or send a pull request, [search](https://github.com/rtfpessoa/diff2html/issues) for previous + discussions about the same feature or issue. Add to the earlier ticket if you find one. -* If you're proposing a new feature, make sure you create an issue to let other contributors know what you are working on. +- If you're proposing a new feature, make sure you create an issue to let other contributors know what you are working + on. -* Before sending a pull request make sure your code is tested. +- Before sending a pull request make sure your code is tested. -* Before sending a pull request for a feature, be sure to run tests with `yarn test`. +- Before sending a pull request for a feature, be sure to run tests with `yarn test`. -* Use the same coding style as the rest of the codebase, most of the check can be performed with `yarn run lint`. +- Use the same coding style as the rest of the codebase, most of the check can be performed with `yarn run lint`. -* Use `git rebase` (not `git merge`) to sync your work from time to time with the master branch. +- Use `git rebase` (not `git merge`) to sync your work from time to time with the master branch. -* After creating your pull request make sure the build is passing on [CircleCI](https://circleci.com/gh/rtfpessoa/diff2html) -and that [Codacy](https://www.codacy.com/app/Codacy/diff2html) is also confident in the code quality. +- After creating your pull request make sure the build is passing on + [CircleCI](https://circleci.com/gh/rtfpessoa/diff2html) and that [Codacy](https://www.codacy.com/app/Codacy/diff2html) + is also confident in the code quality. -* In your pull request, do not commit the `dist` or `build` folder if you needed to build the release files. +- In your pull request, do not commit the `dist` or `build` folder if you needed to build the release files. ### Commit Style -Writing good commit logs is important. A commit log should describe what changed and why. -Follow these guidelines when writing one: +Writing good commit logs is important. A commit log should describe what changed and why. Follow these guidelines when +writing one: -1. The first line should be 50 characters or less and contain a short - description of the change prefixed with the name of the changed - subsystem (e.g. "net: add localAddress and localPort to Socket"). +1. The first line should be 50 characters or less and contain a short description of the change prefixed with the name + of the changed subsystem (e.g. "net: add localAddress and localPort to Socket"). 2. Keep the second line blank. 3. Wrap all other lines at 72 columns. @@ -49,14 +51,11 @@ nicely even when it is indented. By making a contribution to this project, I certify that: -* (a) The contribution was created in whole or in part by me and I - have the right to submit it under the open source license indicated - in the file; or -* (b) The contribution is based upon previous work that, to the best - of my knowledge, is covered under an appropriate open source license - and I have the right under that license to submit that work with - modifications, whether created in whole or in part by me, under the - same open source license (unless I am permitted to submit under a - different license), as indicated in the file; or -* (c) The contribution was provided directly to me by some other - person who certified (a), (b) or (c) and I have not modified it. +- (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source + license indicated in the file; or +- (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate + open source license and I have the right under that license to submit that work with modifications, whether created in + whole or in part by me, under the same open source license (unless I am permitted to submit under a different + license), as indicated in the file; or +- (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not + modified it. diff --git a/CREDITS.md b/CREDITS.md index 8a5f5da..b54cb4e 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -1,12 +1,11 @@ # Credits -This is the list of all the kind people that have contributed to the diff2html project. -This list is ordered by first contribution. +This is the list of all the kind people that have contributed to the diff2html project. This list is ordered by first +contribution. -Thanks, -@rtfpessoa +Thanks, @rtfpessoa ----------- +--- Rodrigo Fernandes, [@rtfpessoa](https://github.com/rtfpessoa) diff --git a/LICENSE.md b/LICENSE.md index 5062db6..922711c 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,20 +1,14 @@ Copyright 2014-2016 Rodrigo Fernandes https://rtfpessoa.github.io/ -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 8382fd6..0985cdb 100644 --- a/README.md +++ b/README.md @@ -2,20 +2,19 @@ [![Codacy Quality Badge](https://api.codacy.com/project/badge/Grade/06412dc3f5a14f568778d0db8a1f7dc8)](https://www.codacy.com/app/rtfpessoa/diff2html?utm_source=github.com&utm_medium=referral&utm_content=rtfpessoa/diff2html&utm_campaign=Badge_Grade) [![Codacy Coverage Badge](https://api.codacy.com/project/badge/Coverage/06412dc3f5a14f568778d0db8a1f7dc8)](https://www.codacy.com/app/rtfpessoa/diff2html?utm_source=github.com&utm_medium=referral&utm_content=rtfpessoa/diff2html&utm_campaign=Badge_Coverage) -![GitHub CI](https://github.com/rtfpessoa/diff2html/workflows/CI/badge.svg) +[![GitHub CI](https://github.com/rtfpessoa/diff2html/workflows/CI/badge.svg?branch=master)](https://github.com/rtfpessoa/diff2html/actions?query=branch%3Amaster) [![npm](https://img.shields.io/npm/v/diff2html.svg)](https://www.npmjs.com/package/diff2html) [![Dependency Status](https://david-dm.org/rtfpessoa/diff2html.svg)](https://david-dm.org/rtfpessoa/diff2html) [![devDependency Status](https://david-dm.org/rtfpessoa/diff2html/dev-status.svg)](https://david-dm.org/rtfpessoa/diff2html#info=devDependencies) [![cdnjs](https://img.shields.io/cdnjs/v/diff2html)](https://cdnjs.com/libraries/diff2html) -[![node](https://img.shields.io/node/v/diff2html.svg)]() -[![npm](https://img.shields.io/npm/l/diff2html.svg)]() +[![node](https://img.shields.io/node/v/diff2html.svg)]() [![npm](https://img.shields.io/npm/l/diff2html.svg)]() [![npm](https://img.shields.io/npm/dm/diff2html.svg)](https://www.npmjs.com/package/diff2html) [![All Contributors](https://img.shields.io/badge/all_contributors-22-orange.svg?style=flat-square)](#contributors-) [![Gitter](https://badges.gitter.im/rtfpessoa/diff2html.svg)](https://gitter.im/rtfpessoa/diff2html?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -diff2html generates pretty HTML diffs from git or unified diff output. +diff2html generates pretty HTML diffs from git diff or unified diff output. [![NPM](https://nodei.co/npm/diff2html.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/diff2html/) @@ -29,7 +28,7 @@ diff2html generates pretty HTML diffs from git or unified diff output. - Inserted and removed lines -- GitHub like style +- GitHub like visual style - Code syntax highlight @@ -44,17 +43,39 @@ diff2html generates pretty HTML diffs from git or unified diff output. ## Distributions - [WebJar](http://www.webjars.org/) -- [Node Module](https://www.npmjs.org/package/diff2html) -- [Node CLI](https://www.npmjs.org/package/diff2html-cli) +- [Node Library](https://www.npmjs.org/package/diff2html) +- [NPM CLI](https://www.npmjs.org/package/diff2html-cli) - Manually download and import: - - Browser - - [bundles/js/diff2html.min.js](./bundles/js/diff2html.min.js) - includes the diff parser and html generator - - [bundles/js/diff2html-ui.min.js](./bundles/js/diff2html-ui.min.js) - includes the wrapper of diff2html that adds highlight, synchronized scroll, and other nice features - - Node.js - - [lib/diff2html.js](./lib/diff2html.js) - targeted for es5, includes the diff parser and html generator - - [lib-esm/diff2html.js](./lib-esm/diff2html.js) - targeted for es6 - includes the diff parser and html generator + - Browser / Bundle + - Parser and HTML Generator + - [bundles/js/diff2html.min.js](./bundles/js/diff2html.min.js) - includes the diff parser and html generator + - Wrapper and helper adding syntax highlight, synchronized scroll, and other nice features + - [bundles/js/diff2html-ui.min.js](./bundles/js/diff2html-ui.min.js) - includes the wrapper of diff2html with + highlight for all `highlight.js` supported languages + - [bundles/js/diff2html-ui-slim.min.js](./bundles/js/diff2html-ui-slim.min.js) - includes the wrapper of diff2html + with "the most common" `highlight.js` supported languages + - [bundles/js/diff2html-ui-base.min.js](./bundles/js/diff2html-ui-base.min.js) - includes the wrapper of diff2html + without including a `highlight.js` implementation. You can use it without syntax highlight or by passing your + own implementation with the languages you prefer + - NPM / Node.js library + - ES5 + - [lib/diff2html.js](./lib/diff2html.js) - includes the diff parser and html generator + - [lib/ui/js/diff2html-ui.js](./lib/ui/js/diff2html-ui.js) - includes the wrapper of diff2html with highlight for + all `highlight.js` supported languages + - [lib/ui/js/diff2html-ui-slim.js](./lib/ui/js/diff2html-ui-slim.js) - includes the wrapper of diff2html with "the + most common" `highlight.js` supported languages + - [lib/ui/js/diff2html-ui-base.js](./lib/ui/js/diff2html-ui-base.js) + - ES6 + - [lib-esm/diff2html.js](./lib-esm/diff2html.js) - includes the diff parser and html generator + - [lib/ui/js/diff2html-ui.js](./lib/ui/js/diff2html-ui.js) - includes the wrapper of diff2html with highlight for + all `highlight.js` supported languages + - [lib/ui/js/diff2html-ui-slim.js](./lib/ui/js/diff2html-ui-slim.js) - includes the wrapper of diff2html with "the + most common" `highlight.js` supported languages + - [lib/ui/js/diff2html-ui-base.js](./lib/ui/js/diff2html-ui-base.js) - includes the wrapper of diff2html without + including a `highlight.js` implementation. You can use it without syntax highlight or by passing your own + implementation with the languages you prefer -## How to use +## Diff2Html Usage To load correctly in the Browser you always need to include the stylesheet in the final HTML. @@ -67,7 +88,41 @@ Import the stylesheet You can also refer to it from a CDN like [CDNJS](https://cdnjs.com/libraries/diff2html). -### Browser Library +### Diff2Html API + +> JSON representation of the diff + + function parse(diffInput: string, configuration: Diff2HtmlConfig = {}): DiffFile[] + +> Pretty HTML representation of the diff + + function html(diffInput: string | DiffFile[], configuration: Diff2HtmlConfig = {}): string + +> Check out the [docs/demo.html](./docs/demo.html) for a demo example. + +### Diff2Html Configuration + +The HTML output accepts a Javascript object with configuration. Possible options: + +- `outputFormat`: the format of the output data: `'line-by-line'` or `'side-by-side'`, default is `'line-by-line'` +- `drawFileList`: show a file list before the diff: `true` or `false`, default is `false` +- `diffStyle`: show differences level in each line: `word` or `char`, default is `word` +- `matching`: matching level: `'lines'` for matching lines, `'words'` for matching lines and words or `'none'`, default + is `none` +- `matchWordsThreshold`: similarity threshold for word matching, default is 0.25 +- `matchingMaxComparisons`: perform at most this much comparisons for line matching a block of changes, default is + `2500` +- `maxLineSizeInBlockForComparison`: maximum number os characters of the bigger line in a block to apply comparison, + default is `200` +- `maxLineLengthHighlight`: only perform diff changes highlight if lines are smaller than this, default is `10000` +- `renderNothingWhenEmpty`: render nothing if the diff shows no change in its comparison: `true` or `false`, default is + `false` +- `compiledTemplates`: object with previously compiled templates to replace parts of the html +- `rawTemplates`: object with raw not compiled templates to replace parts of the html + > For more information regarding the possible templates look into + > [src/templates](https://github.com/rtfpessoa/diff2html/tree/master/src/templates) + +### Diff2Html Browser Import the stylesheet and the library code @@ -82,32 +137,34 @@ Import the stylesheet and the library code It will now be available as a global variable named `Diff2Html`. ```js -document.addEventListener("DOMContentLoaded", () => { - var diffHtml = global.Diff2Html.html("", { +document.addEventListener('DOMContentLoaded', () => { + var diffHtml = global.Diff2Html.html('', { drawFileList: true, - matching: "lines", - outputFormat: "side-by-side" + matching: 'lines', + outputFormat: 'side-by-side', }); - document.getElementById("destination-elem-id").innerHTML = diffHtml; + document.getElementById('destination-elem-id').innerHTML = diffHtml; }); ``` -### Node Module +### Diff2Html NPM / Node.js Library ```js -const Diff2html = require("diff2html"); -const diffJson = Diff2html.parse(""); +const Diff2html = require('diff2html'); +const diffJson = Diff2html.parse(''); const diffHtml = Diff2html.html(diffJson, { drawFileList: true }); -document.getElementById("destination-elem-id").innerHTML = diffHtml; +document.getElementById('destination-elem-id').innerHTML = diffHtml; ``` -### Angular +### Diff2Html Examples + +#### Diff2Html Angular Example - Typescript ```typescript -import * as Diff2Html from "diff2html"; -import { Component, OnInit } from "@angular/core"; +import * as Diff2Html from 'diff2html'; +import { Component, OnInit } from '@angular/core'; export class AppDiffComponent implements OnInit { outputHtml: string; @@ -119,8 +176,8 @@ export class AppDiffComponent implements OnInit { init() { let strInput = - "--- a/server/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go\n+++ b/server/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go\n@@ -1035,6 +1035,17 @@ func Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (\n \n // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n \n+func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {\n+\tr0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)))\n+\tn = int(r0)\n+\tif e1 != 0 {\n+\t\terr = errnoErr(e1)\n+\t}\n+\treturn\n+}\n+\n+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n+\n func read(fd int, p []byte) (n int, err error) {\n \tvar _p0 unsafe.Pointer\n \tif len(p) > 0 {\n"; - let outputHtml = Diff2Html.html(strInput, { drawFileList: true, matching: "lines" }); + '--- a/server/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go\n+++ b/server/vendor/golang.org/x/sys/unix/zsyscall_linux_mipsle.go\n@@ -1035,6 +1035,17 @@ func Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (\n \n // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n \n+func Pselect(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {\n+\tr0, _, e1 := Syscall6(SYS_PSELECT6, uintptr(nfd), uintptr(unsafe.Pointer(r)), uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(e)), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)))\n+\tn = int(r0)\n+\tif e1 != 0 {\n+\t\terr = errnoErr(e1)\n+\t}\n+\treturn\n+}\n+\n+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n+\n func read(fd int, p []byte) (n int, err error) {\n \tvar _p0 unsafe.Pointer\n \tif len(p) > 0 {\n'; + let outputHtml = Diff2Html.html(strInput, { drawFileList: true, matching: 'lines' }); this.outputHtml = outputHtml; } } @@ -148,7 +205,7 @@ export class AppDiffComponent implements OnInit { ] ``` -### Vue.js +#### Diff2Html Vue.js Example ```vue ``` -## API - -> Intermediate Json From Git Word Diff Output - - getJsonFromDiff(input: string, configuration?: Options): Result[] - -> Pretty HTML diff - - getPrettyHtml(input: any, configuration?: Options): string - -> Check out the [docs/demo.html](./docs/demo.html) for a demo example. - -## Configuration - -The HTML output accepts a Javascript object with configuration. Possible options: - -- `inputFormat`: the format of the input data: `'diff'` or `'json'`, default is `'diff'` -- `outputFormat`: the format of the output data: `'line-by-line'` or `'side-by-side'`, default is `'line-by-line'` -- `drawFileList`: show a file list before the diff: `true` or `false`, default is `false` -- `diffStyle`: show differences level in each line: `word` or `char`, default is `word` -- `matching`: matching level: `'lines'` for matching lines, `'words'` for matching lines and words or `'none'`, default is `none` -- `matchWordsThreshold`: similarity threshold for word matching, default is 0.25 -- `matchingMaxComparisons`: perform at most this much comparisons for line matching a block of changes, default is `2500` -- `maxLineSizeInBlockForComparison`: maximum number os characters of the bigger line in a block to apply comparison, default is `200` -- `maxLineLengthHighlight`: only perform diff changes highlight if lines are smaller than this, default is `10000` -- `compiledTemplates`: object with previously compiled templates to replace parts of the html -- `rawTemplates`: object with raw not compiled templates to replace parts of the html -- `renderNothingWhenEmpty`: render nothing if the diff shows no change in its comparison: `true` or `false`, default is `false` - > For more information regarding the possible templates look into [src/templates](https://github.com/rtfpessoa/diff2html/tree/master/src/templates) - -** Diff2HtmlUI Helper Options ** - -- `synchronisedScroll`: scroll both panes in side-by-side mode: `true` or `false`, default is `false` - -> For more information regarding the possible templates look into [src/templates](https://github.com/rtfpessoa/diff2html/tree/master/src/templates) - -## Diff2HtmlUI Helper +## Diff2HtmlUI > Simple wrapper to ease simple tasks in the browser such as: code highlight and js effects @@ -225,7 +245,41 @@ The HTML output accepts a Javascript object with configuration. Possible options - Enable collapsible file summary list - Enable syntax highlight of the code in the diffs -### How to use +### Diff2HtmlUI API + +> Create a Diff2HtmlUI instance + +```ts +constructor(diffInput: string | DiffFile[], target: HTMLElement) // diff2html-ui, diff2html-ui-slim +constructor(diffInput: string | DiffFile[], target: HTMLElement, config: Diff2HtmlUIConfig = {}, hljs?: HighlightJS) // diff2html-ui-base +``` + +> Generate and inject in the document the Pretty HTML representation of the diff + +```ts +draw(): void +``` + +> Enable extra features + +```ts +synchronisedScroll(): void +fileListToggle(startVisible: boolean): void +highlightCode(): void +``` + +> Check out the [docs/demo.html](./docs/demo.html) for a demo example. + +### Diff2HtmlUI Configuration + +- `synchronisedScroll`: scroll both panes in side-by-side mode: `true` or `false`, default is `true` +- `highlight`: syntax highlight the code on the diff: `true` or `false`, default is `true` +- `fileListToggle`: allow the file summary list to be toggled: `true` or `false`, default is `true` +- `fileListStartVisible`: choose if the file summary list starts visible: `true` or `false`, default is `false` +- `smartSelection`: allow selection of the code without including line numbers of line prefixes: `true` or `false`, + default is `true` + +### Diff2HtmlUI Browser #### Mandatory HTML resource imports @@ -240,8 +294,8 @@ The HTML output accepts a Javascript object with configuration. Possible options #### Init ```js -const targetElement = document.getElementById("destination-elem-id"); -const configuration = { drawFileList: true, matching: "lines" }; +const targetElement = document.getElementById('destination-elem-id'); +const configuration = { drawFileList: true, matching: 'lines' }; const diff2htmlUi = new Diff2HtmlUI(diffString, targetElement, configuration); // or @@ -268,7 +322,7 @@ diff2htmlUi.draw(); > Pass the option `highlight` with value true or invoke `diff2htmlUi.highlightCode()` after `diff2htmlUi.draw()`. ```js -document.addEventListener("DOMContentLoaded", () => { +document.addEventListener('DOMContentLoaded', () => { const diffString = `diff --git a/sample.js b/sample.js index 0000001..0ddf2ba --- a/sample.js @@ -276,8 +330,8 @@ index 0000001..0ddf2ba @@ -1 +1 @@ -console.log("Hello World!") +console.log("Hello from Diff2Html!")`; - const targetElement = document.getElementById("myDiffElement"); - const configuration = { inputFormat: "json", drawFileList: true, matching: "lines", highlight: true }; + const targetElement = document.getElementById('myDiffElement'); + const configuration = { inputFormat: 'json', drawFileList: true, matching: 'lines', highlight: true }; const diff2htmlUi = new Diff2HtmlUI(diffString, targetElement, configuration); diff2htmlUi.draw(); diff2htmlUi.highlightCode(); @@ -293,19 +347,19 @@ index 0000001..0ddf2ba ``` -> Invoke the Diff2HtmlUI helper -> Pass the option `fileListToggle` with value true or invoke `diff2htmlUi.fileListToggle()` after `diff2htmlUi.draw()`. +> Invoke the Diff2HtmlUI helper Pass the option `fileListToggle` with value true or invoke +> `diff2htmlUi.fileListToggle()` after `diff2htmlUi.draw()`. ```js -document.addEventListener("DOMContentLoaded", () => { - const targetElement = document.getElementById("myDiffElement"); - var diff2htmlUi = new Diff2HtmlUI(lineDiffExample, targetElement, { drawFileList: true, matching: "lines" }); +document.addEventListener('DOMContentLoaded', () => { + const targetElement = document.getElementById('myDiffElement'); + var diff2htmlUi = new Diff2HtmlUI(lineDiffExample, targetElement, { drawFileList: true, matching: 'lines' }); diff2htmlUi.draw(); diff2htmlUi.fileListToggle(false); }); ``` -# Troubleshooting +## Troubleshooting ### 1. Out of memory or Slow execution @@ -320,9 +374,8 @@ document.addEventListener("DOMContentLoaded", () => { ## Contributions -This is a developer friendly project, all the contributions are welcome. -To contribute just send a pull request with your changes following the guidelines described in `CONTRIBUTING.md`. -I will try to review them as soon as possible. +This is a developer friendly project, all the contributions are welcome. To contribute just send a pull request with +your changes following the guidelines described in `CONTRIBUTING.md`. I will try to review them as soon as possible. ## Contributors ✨ @@ -369,14 +422,16 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d -This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. +Contributions of any kind welcome! ## License -Copyright 2014-2016 Rodrigo Fernandes. Released under the terms of the MIT license. +Copyright 2014-present Rodrigo Fernandes. Released under the terms of the MIT license. ## Thanks -This project is inspired in [pretty-diff](https://github.com/scottgonzalez/pretty-diff) by [Scott González](https://github.com/scottgonzalez). +This project is inspired in [pretty-diff](https://github.com/scottgonzalez/pretty-diff) by +[Scott González](https://github.com/scottgonzalez). --- diff --git a/SECURITY.md b/SECURITY.md index fc06ff7..7ffbdb9 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -9,34 +9,27 @@ ## Reporting a Vulnerability -We take all security bugs in `diff2html` seriously. -Thank you for the help improving the security of `diff2html`. -We appreciate your efforts and responsible disclosure and -will make every effort to acknowledge your contributions. +We take all security bugs in `diff2html` seriously. Thank you for the help improving the security of `diff2html`. We +appreciate your efforts and responsible disclosure and will make every effort to acknowledge your contributions. Report security bugs by emailing the lead maintainer at `rtfrodrigo [at] gmail [dot] com`. -The lead maintainer will acknowledge your email within 48 hours, and will send a -more detailed response within 48 hours indicating the next steps in handling -your report. After the initial reply to your report, the security team will -endeavor to keep you informed of the progress towards a fix and full -announcement, and may ask for additional information or guidance. +The lead maintainer will acknowledge your email within 48 hours, and will send a more detailed response within 48 hours +indicating the next steps in handling your report. After the initial reply to your report, the security team will +endeavor to keep you informed of the progress towards a fix and full announcement, and may ask for additional +information or guidance. -Report security bugs in third-party modules to the person or team maintaining -the module. +Report security bugs in third-party modules to the person or team maintaining the module. ## Disclosure Policy -When the security team receives a security bug report, they will assign it to a -primary handler. This person will coordinate the fix and release process, -involving the following steps: +When the security team receives a security bug report, they will assign it to a primary handler. This person will +coordinate the fix and release process, involving the following steps: - * Confirm the problem and determine the affected versions. - * Audit code to find any potential similar problems. - * Prepare fixes for all releases still under maintenance. These fixes will be - released as fast as possible. +- Confirm the problem and determine the affected versions. +- Audit code to find any potential similar problems. +- Prepare fixes for all releases still under maintenance. These fixes will be released as fast as possible. ## Comments on this Policy -If you have suggestions on how this process could be improved please submit a -pull request. +If you have suggestions on how this process could be improved please submit a pull request. diff --git a/jest.config.js b/jest.config.js index 226b8b0..665cbac 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,15 +1,22 @@ module.exports = { verbose: true, - preset: "ts-jest", - testEnvironment: "node", - coverageDirectory: "./coverage", - coverageReporters: ["lcov", "text", "html"], + preset: 'ts-jest', + testEnvironment: 'node', + coverageDirectory: './coverage', + coverageReporters: ['lcov', 'text', 'html'], + collectCoverageFrom: [ + 'src/**/*.ts', + '!src/ui/**', + '!src/diff2html-templates.ts', + '!src/__tests__/**', + '!node_modules/**', + ], coverageThreshold: { global: { - statements: 94, - branches: 85, + statements: 93, + branches: 86, functions: 98, - lines: 93 - } - } + lines: 93, + }, + }, }; diff --git a/package.json b/package.json index c57486c..e971a92 100644 --- a/package.json +++ b/package.json @@ -35,26 +35,51 @@ "node": ">=10.13" }, "scripts": { - "lint": "eslint '*/**/*.{js,jsx,ts,tsx}'", - "style": "yarn run lint", - "test": "yarn run build-templates && jest", - "coverage": "jest --collectCoverage", - "coverage-html": "yarn run coverage && open ./coverage/index.html", - "codacy": "cat ./coverage/lcov.info | codacy-coverage", - "build": "yarn run build-css && yarn run build-templates && yarn run build-es5 && yarn run build-esm && yarn run build-bundles && yarn run build-website", - "build-es5": "rm -rf lib; tsc -p tsconfig.json --outDir lib", - "build-esm": "rm -rf lib-esm; tsc -p tsconfig.json -m es6 --outDir lib-esm", - "build-bundles": "rm -rf ./bundles/js; NODE_ENV=production WEBPACK_MINIMIZE=true webpack --mode production --config webpack.bundles.ts", - "build-css": "rm -rf ./bundles/css; postcss --use autoprefixer postcss-import postcss-preset-env cssnano -o ./bundles/css/diff2html.min.css ./src/ui/css/diff2html.css", - "build-templates": "ts-node ./scripts/hulk.ts --wrapper ts --variable 'defaultTemplates' ./src/templates/*.mustache > ./src/diff2html-templates.ts", - "build-website": "rm -rf docs; NODE_ENV=production WEBPACK_MINIMIZE=true webpack --mode production --config webpack.website.ts", - "start-website": "WEBPACK_MINIFY=false NODE_ENV=dev webpack-dev-server --mode dev --config webpack.website.ts", - "preversion": "yarn run lint && yarn run build && yarn test", + "eslint": "eslint --ignore-path .gitignore \"**/*.{js,jsx,ts,tsx,json}\"", + "lint:check": "yarn run eslint", + "lint:fix": "yarn run eslint --fix", + "prettier": "prettier --ignore-path .gitignore '**/*.+(js|jsx|ts|tsx|json|css|html|md|mdx)'", + "format:check": "yarn run prettier --check", + "format:fix": "yarn run prettier --write", + "build": "yarn run build:css && yarn run build:templates && yarn run build:es5 && yarn run build:esm && yarn run build:bundles && yarn run build:website", + "build:es5": "rm -rf lib; tsc -p tsconfig.json --outDir lib", + "build:esm": "rm -rf lib-esm; tsc -p tsconfig.json -m es6 --outDir lib-esm", + "build:bundles": "rm -rf ./bundles/js; webpack ---display-reasons --display-modules --mode production --config webpack.bundles.ts", + "build:css": "rm -rf ./bundles/css; postcss --config ./postcss.config.js --no-map -o ./bundles/css/diff2html.min.css ./src/ui/css/diff2html.css", + "build:templates": "ts-node ./scripts/hulk.ts --wrapper ts --variable 'defaultTemplates' ./src/templates/*.mustache > ./src/diff2html-templates.ts", + "build:website": "rm -rf docs; webpack ---display-reasons --display-modules --mode production --config webpack.website.ts", + "test": "is-ci 'test:coverage' 'test:watch'", + "test:coverage": "jest --coverage", + "test:watch": "jest --watch", + "test:debug": "node --inspect-brk ./node_modules/jest/bin/jest.js --runInBand --watch", + "coverage:open": "yarn run test:coverage && open ./coverage/index.html", + "coverage:push": "cat ./coverage/lcov.info | codacy-coverage", + "validate": "yarn run build:templates && yarn run format:check && yarn run lint:check && yarn run build && yarn run test:coverage", + "fix": "yarn run format:fix && yarn run lint:fix", + "start": "yarn run start:website", + "start:website": "webpack-dev-server --mode development --config webpack.website.ts", + "preversion": "yarn run validate", "version": "git add -A package.json" }, "main": "./lib/diff2html.js", "module": "./lib-esm/diff2html.js", "types": "./lib/diff2html.d.ts", + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "**/*.+(js|jsx|ts|tsx|json)": [ + "prettier --write", + "eslint --fix", + "git add" + ], + "**/*.+(css|html|md|mdx)": [ + "prettier --write", + "git add" + ] + }, "dependencies": { "diff": "4.0.1", "hogan.js": "3.0.2" @@ -63,21 +88,20 @@ "highlight.js": "9.17.1" }, "devDependencies": { - "@types/autoprefixer": "9.6.1", "@types/clipboard": "2.0.1", "@types/copy-webpack-plugin": "5.0.0", "@types/diff": "4.0.2", "@types/highlight.js": "9.12.3", "@types/hogan.js": "3.0.0", "@types/html-webpack-plugin": "3.2.1", - "@types/jest": "24.0.24", - "@types/mini-css-extract-plugin": "0.8.0", + "@types/jest": "24.0.25", + "@types/mini-css-extract-plugin": "0.9.0", "@types/mkdirp": "0.5.2", - "@types/node": "12.12.21", + "@types/node": "13.1.1", "@types/nopt": "3.0.29", "@types/webpack": "4.41.0", - "@typescript-eslint/eslint-plugin": "2.12.0", - "@typescript-eslint/parser": "2.12.0", + "@typescript-eslint/eslint-plugin": "2.13.0", + "@typescript-eslint/parser": "2.13.0", "autoprefixer": "9.7.3", "bootstrap": "3.4.1", "clipboard": "2.0.4", @@ -86,37 +110,38 @@ "css-loader": "3.4.0", "cssnano": "4.1.10", "eslint": "6.8.0", - "eslint-config-prettier": "6.7.0", - "eslint-config-standard": "14.1.0", + "eslint-config-prettier": "6.9.0", "eslint-plugin-import": "2.19.1", - "eslint-plugin-jest": "23.1.1", - "eslint-plugin-node": "10.0.0", - "eslint-plugin-prettier": "3.1.2", + "eslint-plugin-jest": "23.2.0", + "eslint-plugin-json": "2.0.1", + "eslint-plugin-node": "11.0.0", + "eslint-plugin-optimize-regex": "1.1.7", "eslint-plugin-promise": "4.2.1", - "eslint-plugin-standard": "4.0.1", - "fast-html-parser": "1.0.1", + "eslint-plugin-sonarjs": "0.5.0", "file-loader": "5.0.2", "handlebars": "4.5.3", "handlebars-loader": "1.7.1", "html-webpack-plugin": "3.2.0", + "husky": "3.1.0", "image-webpack-loader": "6.0.0", + "is-ci-cli": "2.0.0", "jest": "24.9.0", + "lint-staged": "9.5.0", "mini-css-extract-plugin": "0.9.0", "mkdirp": "0.5.1", "nopt": "4.0.1", + "postcss": "7.0.25", "postcss-cli": "6.1.3", "postcss-import": "12.0.1", "postcss-loader": "3.0.0", - "postcss-normalize": "8.0.1", "postcss-preset-env": "6.7.0", "prettier": "1.19.1", - "style-loader": "1.1.1", "ts-jest": "24.2.0", "ts-loader": "6.2.1", "ts-node": "8.5.4", "typescript": "3.7.4", "url-loader": "3.0.0", - "webpack": "4.41.4", + "webpack": "4.41.5", "webpack-cli": "3.3.10", "webpack-dev-server": "3.10.1", "whatwg-fetch": "3.0.0" diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..df76dd0 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,10 @@ +module.exports = { + sourceMap: false, + plugins: { + 'postcss-import': {}, + 'postcss-preset-env': { + browsers: 'last 2 versions', + }, + cssnano: {}, + }, +}; diff --git a/scripts/hulk.ts b/scripts/hulk.ts index f3e4c4a..6608f49 100755 --- a/scripts/hulk.ts +++ b/scripts/hulk.ts @@ -1,5 +1,3 @@ -#!/usr/bin/env node - /* * Copyright 2011 Twitter, Inc. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,12 +13,12 @@ * limitations under the License. */ -import * as path from "path"; -import * as fs from "fs"; +import * as path from 'path'; +import * as fs from 'fs'; -import * as hogan from "hogan.js"; -import nopt from "nopt"; -import * as mkderp from "mkdirp"; +import * as hogan from 'hogan.js'; +import nopt from 'nopt'; +import * as mkderp from 'mkdirp'; const options = nopt( { @@ -29,47 +27,47 @@ const options = nopt( variable: String, wrapper: String, version: true, - help: true + help: true, }, { - n: ["--namespace"], - o: ["--outputdir"], - vn: ["--variable"], - w: ["--wrapper"], - h: ["--help"], - v: ["--version"] - } + n: ['--namespace'], + o: ['--outputdir'], + vn: ['--variable'], + w: ['--wrapper'], + h: ['--help'], + v: ['--version'], + }, ); -const specials = ["/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\"]; -const specialsRegExp = new RegExp("(\\" + specials.join("|\\") + ")", "g"); +const specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\']; +const specialsRegExp = new RegExp('(\\' + specials.join('|\\') + ')', 'g'); function escape(text: string): string { - return text.replace(specialsRegExp, "\\$1"); + return text.replace(specialsRegExp, '\\$1'); } function cyan(text: string): string { - return "\x1B[36m" + text + "\x1B[39m"; + return '\x1B[36m' + text + '\x1B[39m'; } function extractFiles(files: string[]): string[] { const usage = `${cyan( - "USAGE:" + 'USAGE:', )} hulk [--wrapper wrapper] [--outputdir outputdir] [--namespace namespace] [--variable variable] FILES - ${cyan("OPTIONS:")} [-w, --wrapper] :: wraps the template (i.e. amd) + ${cyan('OPTIONS:')} [-w, --wrapper] :: wraps the template (i.e. amd) [-o, --outputdir] :: outputs the templates as individual files to a directory [-n, --namespace] :: prepend string to template names [-vn, --variable] :: variable name for non-amd wrapper - ${cyan("EXAMPLE:")} hulk --wrapper amd ./templates/*.mustache + ${cyan('EXAMPLE:')} hulk --wrapper amd ./templates/*.mustache - ${cyan("NOTE:")} hulk supports the "*" wildcard and allows you to target specific extensions too + ${cyan('NOTE:')} hulk supports the "*" wildcard and allows you to target specific extensions too `; if (options.version) { - console.log(require("../package.json").version); + console.log(require('../package.json').version); process.exit(0); } @@ -78,20 +76,18 @@ function extractFiles(files: string[]): string[] { process.exit(0); } - const templateFiles = files + return files .map((fileGlob: string) => { if (/\*/.test(fileGlob)) { - const [fileGlobPrefix, fileGlobSuffix] = fileGlob.split("*"); + const [fileGlobPrefix, fileGlobSuffix] = fileGlob.split('*'); - const files = fs.readdirSync(fileGlobPrefix || ".").reduce((previousFiles, relativeFilePath) => { + return fs.readdirSync(fileGlobPrefix || '.').reduce((previousFiles, relativeFilePath) => { const file = path.join(fileGlobPrefix, relativeFilePath); if (new RegExp(`${escape(fileGlobSuffix)}$`).test(relativeFilePath) && fs.statSync(file).isFile()) { previousFiles.push(file); } return previousFiles; }, []); - - return files; } else if (fs.statSync(fileGlob).isFile()) { return [fileGlob]; } else { @@ -99,8 +95,6 @@ function extractFiles(files: string[]): string[] { } }) .reduce((previous, current) => previous.concat(current), []); - - return templateFiles; } // Remove utf-8 byte order mark, http://en.wikipedia.org/wiki/Byte_order_mark @@ -115,21 +109,21 @@ function removeByteOrderMark(text: string): string { function wrap(file: string, name: string, openedFile: string): string { const hoganTemplateString = `new Hogan.Template(${hogan.compile(openedFile, { asString: true })})`; - const objectName = options.variable || "templates"; + const objectName = options.variable || 'templates'; const objectAccessor = `${objectName}["${name}"]`; const objectStmt = `${objectAccessor} = ${hoganTemplateString};`; switch (options.wrapper) { - case "amd": + case 'amd': return `define(${ - !options.outputdir ? `"${path.join(path.dirname(file), name)}", ` : "" + !options.outputdir ? `"${path.join(path.dirname(file), name)}", ` : '' }["hogan.js"], function(Hogan) { return ${hoganTemplateString}; });`; - case "node": + case 'node': // If we have a template per file the export will expose the template directly return options.outputdir ? `global.${objectStmt};\nmodule.exports = ${objectAccessor};` : `global.${objectStmt}`; - case "ts": + case 'ts': return `// @ts-ignore\n${objectStmt}`; default: return objectStmt; @@ -137,25 +131,25 @@ function wrap(file: string, name: string, openedFile: string): string { } function prepareOutput(content: string): string { - const variableName = options.variable || "templates"; + const variableName = options.variable || 'templates'; switch (options.wrapper) { - case "amd": + case 'amd': return content; - case "node": + case 'node': return `(function() { if (!!!global.${variableName}) global.${variableName} = {}; var Hogan = require("hogan.js"); ${content} -${!options.outputdir ? `module.exports = global.${variableName};\n` : ""})();`; +${!options.outputdir ? `module.exports = global.${variableName};\n` : ''})();`; - case "ts": + case 'ts': return `import * as Hogan from "hogan.js"; type CompiledTemplates = { [name: string]: Hogan.Template }; export const ${variableName}: CompiledTemplates = {}; ${content}`; default: - return "if (!!!" + variableName + ") var " + variableName + " = {};\n" + content; + return 'if (!!!' + variableName + ') var ' + variableName + ' = {};\n' + content; } } @@ -166,28 +160,28 @@ if (options.outputdir) { // Prepend namespace to template name function namespace(name: string): string { - return (options.namespace || "") + name; + return (options.namespace || '') + name; } // Write a template foreach file that matches template extension const templates = extractFiles(options.argv.remain) .map(file => { - const timmedFileContents = fs.readFileSync(file, "utf8").trim(); + const timmedFileContents = fs.readFileSync(file, 'utf8').trim(); if (!timmedFileContents) return; - const name = namespace(path.basename(file).replace(/\..*$/, "")); + const name = namespace(path.basename(file).replace(/\..*$/, '')); const cleanFileContents = wrap(file, name, removeByteOrderMark(timmedFileContents)); if (!options.outputdir) return cleanFileContents; - const fileExtension = options.wrapper === "ts" ? "ts" : "js"; + const fileExtension = options.wrapper === 'ts' ? 'ts' : 'js'; return fs.writeFileSync(path.join(options.outputdir, `${name}.${fileExtension}`), prepareOutput(cleanFileContents)); }) - .filter(templateContents => typeof templateContents !== "undefined"); + .filter(templateContents => typeof templateContents !== 'undefined'); // Output templates if (!templates.length || options.outputdir) process.exit(0); -console.log(prepareOutput(templates.join("\n"))); +console.log(prepareOutput(templates.join('\n'))); diff --git a/src/__tests__/diff-parser-tests.ts b/src/__tests__/diff-parser-tests.ts index 2238758..5768d8c 100644 --- a/src/__tests__/diff-parser-tests.ts +++ b/src/__tests__/diff-parser-tests.ts @@ -1,17 +1,17 @@ -import { parse } from "../diff-parser"; +import { parse } from '../diff-parser'; -describe("DiffParser", () => { - describe("generateDiffJson", () => { +describe('DiffParser', () => { + describe('generateDiffJson', () => { // eslint-disable-next-line jest/expect-expect - it("should parse unix with \n diff", () => { + it('should parse unix with \n diff', () => { const diff = - "diff --git a/sample b/sample\n" + - "index 0000001..0ddf2ba\n" + - "--- a/sample\n" + - "+++ b/sample\n" + - "@@ -1 +1 @@\n" + - "-test\n" + - "+test1r\n"; + 'diff --git a/sample b/sample\n' + + 'index 0000001..0ddf2ba\n' + + '--- a/sample\n' + + '+++ b/sample\n' + + '@@ -1 +1 @@\n' + + '-test\n' + + '+test1r\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -53,15 +53,15 @@ describe("DiffParser", () => { }); // eslint-disable-next-line jest/expect-expect - it("should parse windows with \r\n diff", () => { + it('should parse windows with \r\n diff', () => { const diff = - "diff --git a/sample b/sample\r\n" + - "index 0000001..0ddf2ba\r\n" + - "--- a/sample\r\n" + - "+++ b/sample\r\n" + - "@@ -1 +1 @@\r\n" + - "-test\r\n" + - "+test1r\r\n"; + 'diff --git a/sample b/sample\r\n' + + 'index 0000001..0ddf2ba\r\n' + + '--- a/sample\r\n' + + '+++ b/sample\r\n' + + '@@ -1 +1 @@\r\n' + + '-test\r\n' + + '+test1r\r\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -103,15 +103,15 @@ describe("DiffParser", () => { }); // eslint-disable-next-line jest/expect-expect - it("should parse old os x with \r diff", () => { + it('should parse old os x with \r diff', () => { const diff = - "diff --git a/sample b/sample\r" + - "index 0000001..0ddf2ba\r" + - "--- a/sample\r" + - "+++ b/sample\r" + - "@@ -1 +1 @@\r" + - "-test\r" + - "+test1r\r"; + 'diff --git a/sample b/sample\r' + + 'index 0000001..0ddf2ba\r' + + '--- a/sample\r' + + '+++ b/sample\r' + + '@@ -1 +1 @@\r' + + '-test\r' + + '+test1r\r'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -153,15 +153,15 @@ describe("DiffParser", () => { }); // eslint-disable-next-line jest/expect-expect - it("should parse mixed eols diff", () => { + it('should parse mixed eols diff', () => { const diff = - "diff --git a/sample b/sample\n" + - "index 0000001..0ddf2ba\r\n" + - "--- a/sample\r" + - "+++ b/sample\r\n" + - "@@ -1 +1 @@\n" + - "-test\r" + - "+test1r\n"; + 'diff --git a/sample b/sample\n' + + 'index 0000001..0ddf2ba\r\n' + + '--- a/sample\r' + + '+++ b/sample\r\n' + + '@@ -1 +1 @@\n' + + '-test\r' + + '+test1r\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -202,16 +202,16 @@ describe("DiffParser", () => { `); }); - it("should parse diff with special characters", () => { + it('should parse diff with special characters', () => { const diff = 'diff --git "a/bla with \ttab.scala" "b/bla with \ttab.scala"\n' + - "index 4c679d7..e9bd385 100644\n" + + 'index 4c679d7..e9bd385 100644\n' + '--- "a/bla with \ttab.scala"\n' + '+++ "b/bla with \ttab.scala"\n' + - "@@ -1 +1,2 @@\n" + - "-cenas\n" + - "+cenas com ananas\n" + - "+bananas"; + '@@ -1 +1,2 @@\n' + + '-cenas\n' + + '+cenas com ananas\n' + + '+bananas'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -259,16 +259,16 @@ describe("DiffParser", () => { `); }); - it("should parse diff with prefix", () => { + it('should parse diff with prefix', () => { const diff = 'diff --git "\tbla with \ttab.scala" "\tbla with \ttab.scala"\n' + - "index 4c679d7..e9bd385 100644\n" + + 'index 4c679d7..e9bd385 100644\n' + '--- "\tbla with \ttab.scala"\n' + '+++ "\tbla with \ttab.scala"\n' + - "@@ -1 +1,2 @@\n" + - "-cenas\n" + - "+cenas com ananas\n" + - "+bananas"; + '@@ -1 +1,2 @@\n' + + '-cenas\n' + + '+cenas com ananas\n' + + '+bananas'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -316,17 +316,17 @@ describe("DiffParser", () => { `); }); - it("should parse diff with deleted file", () => { + it('should parse diff with deleted file', () => { const diff = - "diff --git a/src/var/strundefined.js b/src/var/strundefined.js\n" + - "deleted file mode 100644\n" + - "index 04e16b0..0000000\n" + - "--- a/src/var/strundefined.js\n" + - "+++ /dev/null\n" + - "@@ -1,3 +0,0 @@\n" + - "-define(() => {\n" + - "- return typeof undefined;\n" + - "-});\n"; + 'diff --git a/src/var/strundefined.js b/src/var/strundefined.js\n' + + 'deleted file mode 100644\n' + + 'index 04e16b0..0000000\n' + + '--- a/src/var/strundefined.js\n' + + '+++ /dev/null\n' + + '@@ -1,3 +0,0 @@\n' + + '-define(() => {\n' + + '- return typeof undefined;\n' + + '-});\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -375,19 +375,19 @@ describe("DiffParser", () => { `); }); - it("should parse diff with new file", () => { + it('should parse diff with new file', () => { const diff = - "diff --git a/test.js b/test.js\n" + - "new file mode 100644\n" + - "index 0000000..e1e22ec\n" + - "--- /dev/null\n" + - "+++ b/test.js\n" + - "@@ -0,0 +1,5 @@\n" + + 'diff --git a/test.js b/test.js\n' + + 'new file mode 100644\n' + + 'index 0000000..e1e22ec\n' + + '--- /dev/null\n' + + '+++ b/test.js\n' + + '@@ -0,0 +1,5 @@\n' + "+var parser = require('./source/git-parser');\n" + - "+\n" + - "+var patchLineList = [ false, false, false, false ];\n" + - "+\n" + - "+console.log(parser.parsePatchDiffResult(text, patchLineList));\n"; + '+\n' + + '+var patchLineList = [ false, false, false, false ];\n' + + '+\n' + + '+console.log(parser.parsePatchDiffResult(text, patchLineList));\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -448,19 +448,19 @@ describe("DiffParser", () => { `); }); - it("should parse diff with nested diff", () => { + it('should parse diff with nested diff', () => { const diff = - "diff --git a/src/offset.js b/src/offset.js\n" + - "index cc6ffb4..fa51f18 100644\n" + - "--- a/src/offset.js\n" + - "+++ b/src/offset.js\n" + - "@@ -1,6 +1,5 @@\n" + + 'diff --git a/src/offset.js b/src/offset.js\n' + + 'index cc6ffb4..fa51f18 100644\n' + + '--- a/src/offset.js\n' + + '+++ b/src/offset.js\n' + + '@@ -1,6 +1,5 @@\n' + "+var parser = require('./source/git-parser');\n" + - "+\n" + + '+\n' + "+var text = 'diff --git a/components/app/app.html b/components/app/app.html\\nindex ecb7a95..027bd9b 100644\\n--- a/components/app/app.html\\n+++ b/components/app/app.html\\n@@ -52,0 +53,3 @@\\n+\\n+\\n+\\n@@ -56,0 +60,3 @@\\n+\\n+\\n+\\n'\n" + - "+var patchLineList = [ false, false, false, false ];\n" + - "+\n" + - "+console.log(parser.parsePatchDiffResult(text, patchLineList));\n"; + '+var patchLineList = [ false, false, false, false ];\n' + + '+\n' + + '+console.log(parser.parsePatchDiffResult(text, patchLineList));\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -526,32 +526,32 @@ describe("DiffParser", () => { `); }); - it("should parse diff with multiple blocks", () => { + it('should parse diff with multiple blocks', () => { const diff = - "diff --git a/src/attributes/classes.js b/src/attributes/classes.js\n" + - "index c617824..c8d1393 100644\n" + - "--- a/src/attributes/classes.js\n" + - "+++ b/src/attributes/classes.js\n" + - "@@ -1,10 +1,9 @@\n" + - " define([\n" + + 'diff --git a/src/attributes/classes.js b/src/attributes/classes.js\n' + + 'index c617824..c8d1393 100644\n' + + '--- a/src/attributes/classes.js\n' + + '+++ b/src/attributes/classes.js\n' + + '@@ -1,10 +1,9 @@\n' + + ' define([\n' + ' "../core",\n' + ' "../var/rnotwhite",\n' + '- "../var/strundefined",\n' + ' "../data/var/dataPriv",\n' + ' "../core/init"\n' + - "-], function( jQuery, rnotwhite, strundefined, dataPriv ) {\n" + - "+], function( jQuery, rnotwhite, dataPriv ) {\n" + - " \n" + - " var rclass = /[\\t\\r\\n\\f]/g;\n" + - " \n" + - "@@ -128,7 +127,7 @@ jQuery.fn.extend({\n" + - " }\n" + - " \n" + - " // Toggle whole class name\n" + + '-], function( jQuery, rnotwhite, strundefined, dataPriv ) {\n' + + '+], function( jQuery, rnotwhite, dataPriv ) {\n' + + ' \n' + + ' var rclass = /[\\t\\r\\n\\f]/g;\n' + + ' \n' + + '@@ -128,7 +127,7 @@ jQuery.fn.extend({\n' + + ' }\n' + + ' \n' + + ' // Toggle whole class name\n' + '- } else if ( type === strundefined || type === "boolean" ) {\n' + '+ } else if ( value === undefined || type === "boolean" ) {\n' + - " if ( this.className ) {\n" + - " // store className if set\n" + + ' if ( this.className ) {\n' + + ' // store className if set\n' + ' dataPriv.set( this, "__className__", this.className );\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` @@ -704,27 +704,27 @@ describe("DiffParser", () => { `); }); - it("should parse diff with multiple files", () => { + it('should parse diff with multiple files', () => { const diff = - "diff --git a/src/core/init.js b/src/core/init.js\n" + - "index e49196a..50f310c 100644\n" + - "--- a/src/core/init.js\n" + - "+++ b/src/core/init.js\n" + - "@@ -101,7 +101,7 @@ var rootjQuery,\n" + - " // HANDLE: $(function)\n" + - " // Shortcut for document ready\n" + - " } else if ( jQuery.isFunction( selector ) ) {\n" + + 'diff --git a/src/core/init.js b/src/core/init.js\n' + + 'index e49196a..50f310c 100644\n' + + '--- a/src/core/init.js\n' + + '+++ b/src/core/init.js\n' + + '@@ -101,7 +101,7 @@ var rootjQuery,\n' + + ' // HANDLE: $(function)\n' + + ' // Shortcut for document ready\n' + + ' } else if ( jQuery.isFunction( selector ) ) {\n' + '- return typeof rootjQuery.ready !== "undefined" ?\n' + - "+ return rootjQuery.ready !== undefined ?\n" + - " rootjQuery.ready( selector ) :\n" + - " // Execute immediately if ready is not present\n" + - " selector( jQuery );\n" + - "diff --git a/src/event.js b/src/event.js\n" + - "index 7336f4d..6183f70 100644\n" + - "--- a/src/event.js\n" + - "+++ b/src/event.js\n" + - "@@ -1,6 +1,5 @@\n" + - " define([\n" + + '+ return rootjQuery.ready !== undefined ?\n' + + ' rootjQuery.ready( selector ) :\n' + + ' // Execute immediately if ready is not present\n' + + ' selector( jQuery );\n' + + 'diff --git a/src/event.js b/src/event.js\n' + + 'index 7336f4d..6183f70 100644\n' + + '--- a/src/event.js\n' + + '+++ b/src/event.js\n' + + '@@ -1,6 +1,5 @@\n' + + ' define([\n' + ' "./core",\n' + '- "./var/strundefined",\n' + ' "./var/rnotwhite",\n' + @@ -865,35 +865,35 @@ describe("DiffParser", () => { `); }); - it("should parse combined diff", () => { + it('should parse combined diff', () => { const diff = - "diff --combined describe.c\n" + - "index fabadb8,cc95eb0..4866510\n" + - "--- a/describe.c\n" + - "+++ b/describe.c\n" + - "@@@ -98,20 -98,12 +98,20 @@@\n" + - " return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;\n" + - " }\n" + - " \n" + - "- static void describe(char *arg)\n" + - " -static void describe(struct commit *cmit, int last_one)\n" + - "++static void describe(char *arg, int last_one)\n" + - " {\n" + - " + unsigned char sha1[20];\n" + - " + struct commit *cmit;\n" + - " struct commit_list *list;\n" + - " static int initialized = 0;\n" + - " struct commit_name *n;\n" + - " \n" + - " + if (get_sha1(arg, sha1) < 0)\n" + - " + usage(describe_usage);\n" + - " + cmit = lookup_commit_reference(sha1);\n" + - " + if (!cmit)\n" + - " + usage(describe_usage);\n" + - " +\n" + - " if (!initialized) {\n" + - " initialized = 1;\n" + - " for_each_ref(get_name);\n"; + 'diff --combined describe.c\n' + + 'index fabadb8,cc95eb0..4866510\n' + + '--- a/describe.c\n' + + '+++ b/describe.c\n' + + '@@@ -98,20 -98,12 +98,20 @@@\n' + + ' return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;\n' + + ' }\n' + + ' \n' + + '- static void describe(char *arg)\n' + + ' -static void describe(struct commit *cmit, int last_one)\n' + + '++static void describe(char *arg, int last_one)\n' + + ' {\n' + + ' + unsigned char sha1[20];\n' + + ' + struct commit *cmit;\n' + + ' struct commit_list *list;\n' + + ' static int initialized = 0;\n' + + ' struct commit_name *n;\n' + + ' \n' + + ' + if (get_sha1(arg, sha1) < 0)\n' + + ' + usage(describe_usage);\n' + + ' + cmit = lookup_commit_reference(sha1);\n' + + ' + if (!cmit)\n' + + ' + usage(describe_usage);\n' + + ' +\n' + + ' if (!initialized) {\n' + + ' initialized = 1;\n' + + ' for_each_ref(get_name);\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1057,12 +1057,12 @@ describe("DiffParser", () => { `); }); - it("should parse diffs with copied files", () => { + it('should parse diffs with copied files', () => { const diff = - "diff --git a/index.js b/more-index.js\n" + - "dissimilarity index 5%\n" + - "copy from index.js\n" + - "copy to more-index.js\n"; + 'diff --git a/index.js b/more-index.js\n' + + 'dissimilarity index 5%\n' + + 'copy from index.js\n' + + 'copy to more-index.js\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1080,12 +1080,12 @@ describe("DiffParser", () => { `); }); - it("should parse diffs with moved files", () => { + it('should parse diffs with moved files', () => { const diff = - "diff --git a/more-index.js b/other-index.js\n" + - "similarity index 86%\n" + - "rename from more-index.js\n" + - "rename to other-index.js\n"; + 'diff --git a/more-index.js b/other-index.js\n' + + 'similarity index 86%\n' + + 'rename from more-index.js\n' + + 'rename to other-index.js\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1103,15 +1103,15 @@ describe("DiffParser", () => { `); }); - it("should parse diffs correct line numbers", () => { + it('should parse diffs correct line numbers', () => { const diff = - "diff --git a/sample b/sample\n" + - "index 0000001..0ddf2ba\n" + - "--- a/sample\n" + - "+++ b/sample\n" + - "@@ -1 +1,2 @@\n" + - "-test\n" + - "+test1r\n"; + 'diff --git a/sample b/sample\n' + + 'index 0000001..0ddf2ba\n' + + '--- a/sample\n' + + '+++ b/sample\n' + + '@@ -1 +1,2 @@\n' + + '-test\n' + + '+test1r\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1152,23 +1152,23 @@ describe("DiffParser", () => { `); }); - it("should parse unified non git diff and strip timestamps off the headers", () => { + it('should parse unified non git diff and strip timestamps off the headers', () => { const diffs = [ // 2 hours ahead of GMT - "--- a/sample.js 2016-10-25 11:37:14.000000000 +0200\n" + - "+++ b/sample.js 2016-10-25 11:37:14.000000000 +0200\n" + - "@@ -1 +1,2 @@\n" + - "-test\n" + - "+test1r\n" + - "+test2r", + '--- a/sample.js 2016-10-25 11:37:14.000000000 +0200\n' + + '+++ b/sample.js 2016-10-25 11:37:14.000000000 +0200\n' + + '@@ -1 +1,2 @@\n' + + '-test\n' + + '+test1r\n' + + '+test2r', // 2 hours behind GMT - "--- a/sample.js 2016-10-25 11:37:14.000000000 -0200\n" + - "+++ b/sample.js 2016-10-25 11:37:14.000000000 -0200\n" + - "@@ -1 +1,2 @@\n" + - "-test\n" + - "+test1r\n" + - "+test2r" - ].join("\n"); + '--- a/sample.js 2016-10-25 11:37:14.000000000 -0200\n' + + '+++ b/sample.js 2016-10-25 11:37:14.000000000 -0200\n' + + '@@ -1 +1,2 @@\n' + + '-test\n' + + '+test1r\n' + + '+test2r', + ].join('\n'); const result = parse(diffs); expect(result).toMatchInlineSnapshot(` Array [ @@ -1248,9 +1248,9 @@ describe("DiffParser", () => { `); }); - it("should parse unified non git diff", () => { + it('should parse unified non git diff', () => { const diff = - "--- a/sample.js\n" + "+++ b/sample.js\n" + "@@ -1 +1,2 @@\n" + "-test\n" + "+test1r\n" + "+test2r\n"; + '--- a/sample.js\n' + '+++ b/sample.js\n' + '@@ -1 +1,2 @@\n' + '-test\n' + '+test1r\n' + '+test2r\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1294,18 +1294,18 @@ describe("DiffParser", () => { `); }); - it("should parse unified diff with multiple hunks and files", () => { + it('should parse unified diff with multiple hunks and files', () => { const diff = - "--- sample.js\n" + - "+++ sample.js\n" + - "@@ -1 +1,2 @@\n" + - "-test\n" + - "@@ -10 +20,2 @@\n" + - "+test\n" + - "--- sample1.js\n" + - "+++ sample1.js\n" + - "@@ -1 +1,2 @@\n" + - "+test1"; + '--- sample.js\n' + + '+++ sample.js\n' + + '@@ -1 +1,2 @@\n' + + '-test\n' + + '@@ -10 +20,2 @@\n' + + '+test\n' + + '--- sample1.js\n' + + '+++ sample1.js\n' + + '@@ -1 +1,2 @@\n' + + '+test1'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1375,20 +1375,20 @@ describe("DiffParser", () => { `); }); - it("should parse diff with --- and +++ in the context lines", () => { + it('should parse diff with --- and +++ in the context lines', () => { const diff = - "--- sample.js\n" + - "+++ sample.js\n" + - "@@ -1,8 +1,8 @@\n" + - " test\n" + - " \n" + - "-- 1\n" + - "--- 1\n" + - "---- 1\n" + - " \n" + - "++ 2\n" + - "+++ 2\n" + - "++++ 2"; + '--- sample.js\n' + + '+++ sample.js\n' + + '@@ -1,8 +1,8 @@\n' + + ' test\n' + + ' \n' + + '-- 1\n' + + '--- 1\n' + + '---- 1\n' + + ' \n' + + '++ 2\n' + + '+++ 2\n' + + '++++ 2'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1468,8 +1468,8 @@ describe("DiffParser", () => { `); }); - it("should parse diff without proper hunk headers", () => { - const diff = "--- sample.js\n" + "+++ sample.js\n" + "@@ @@\n" + " test"; + it('should parse diff without proper hunk headers', () => { + const diff = '--- sample.js\n' + '+++ sample.js\n' + '@@ @@\n' + ' test'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1501,13 +1501,13 @@ describe("DiffParser", () => { `); }); - it("should parse binary file diff", () => { + it('should parse binary file diff', () => { const diff = - "diff --git a/last-changes-config.png b/last-changes-config.png\n" + - "index 322248b..56fc1f2 100644\n" + - "--- a/last-changes-config.png\n" + - "+++ b/last-changes-config.png\n" + - "Binary files differ"; + 'diff --git a/last-changes-config.png b/last-changes-config.png\n' + + 'index 322248b..56fc1f2 100644\n' + + '--- a/last-changes-config.png\n' + + '+++ b/last-changes-config.png\n' + + 'Binary files differ'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1536,21 +1536,21 @@ describe("DiffParser", () => { `); }); - it("should parse diff with --find-renames", () => { + it('should parse diff with --find-renames', () => { const diff = - "diff --git a/src/test-bar.js b/src/test-baz.js\n" + - "similarity index 98%\n" + - "rename from src/test-bar.js\n" + - "rename to src/test-baz.js\n" + - "index e01513b..f14a870 100644\n" + - "--- a/src/test-bar.js\n" + - "+++ b/src/test-baz.js\n" + - "@@ -1,4 +1,32 @@\n" + - " function foo() {\n" + + 'diff --git a/src/test-bar.js b/src/test-baz.js\n' + + 'similarity index 98%\n' + + 'rename from src/test-bar.js\n' + + 'rename to src/test-baz.js\n' + + 'index e01513b..f14a870 100644\n' + + '--- a/src/test-bar.js\n' + + '+++ b/src/test-baz.js\n' + + '@@ -1,4 +1,32 @@\n' + + ' function foo() {\n' + '-var bar = "Whoops!";\n' + '+var baz = "Whoops!";\n' + - " }\n" + - " "; + ' }\n' + + ' '; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1612,49 +1612,49 @@ describe("DiffParser", () => { `); }); - it("should parse diff with prefix 2", () => { + it('should parse diff with prefix 2', () => { const diff = 'diff --git "\tTest.scala" "\tScalaTest.scala"\n' + - "similarity index 88%\n" + - "rename from Test.scala\n" + - "rename to ScalaTest.scala\n" + - "index 7d1f9bf..8b13271 100644\n" + + 'similarity index 88%\n' + + 'rename from Test.scala\n' + + 'rename to ScalaTest.scala\n' + + 'index 7d1f9bf..8b13271 100644\n' + '--- "\tTest.scala"\n' + '+++ "\tScalaTest.scala"\n' + - "@@ -1,6 +1,8 @@\n" + - " class Test {\n" + - " \n" + - " def method1 = ???\n" + - "+\n" + - "+ def method2 = ???\n" + - " \n" + - " def myMethod = ???\n" + - " \n" + - "@@ -10,7 +12,6 @@ class Test {\n" + - " \n" + - " def + = ???\n" + - " \n" + - "- def |> = ???\n" + - " \n" + - " }\n" + - " \n" + + '@@ -1,6 +1,8 @@\n' + + ' class Test {\n' + + ' \n' + + ' def method1 = ???\n' + + '+\n' + + '+ def method2 = ???\n' + + ' \n' + + ' def myMethod = ???\n' + + ' \n' + + '@@ -10,7 +12,6 @@ class Test {\n' + + ' \n' + + ' def + = ???\n' + + ' \n' + + '- def |> = ???\n' + + ' \n' + + ' }\n' + + ' \n' + 'diff --git "\ttardis.png" "\ttardis.png"\n' + - "new file mode 100644\n" + - "index 0000000..d503a29\n" + + 'new file mode 100644\n' + + 'index 0000000..d503a29\n' + 'Binary files /dev/null and "\ttardis.png" differ\n' + - "diff --git a/src/test-bar.js b/src/test-baz.js\n" + - "similarity index 98%\n" + - "rename from src/test-bar.js\n" + - "rename to src/test-baz.js\n" + - "index e01513b..f14a870 100644\n" + - "--- a/src/test-bar.js\n" + - "+++ b/src/test-baz.js\n" + - "@@ -1,4 +1,32 @@\n" + - " function foo() {\n" + + 'diff --git a/src/test-bar.js b/src/test-baz.js\n' + + 'similarity index 98%\n' + + 'rename from src/test-bar.js\n' + + 'rename to src/test-baz.js\n' + + 'index e01513b..f14a870 100644\n' + + '--- a/src/test-bar.js\n' + + '+++ b/src/test-baz.js\n' + + '@@ -1,4 +1,32 @@\n' + + ' function foo() {\n' + '-var bar = "Whoops!";\n' + '+var baz = "Whoops!";\n' + - " }\n" + - " "; + ' }\n' + + ' '; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -1860,39 +1860,39 @@ describe("DiffParser", () => { `); }); - it("should parse binary with content", () => { + it('should parse binary with content', () => { const diff = - "diff --git a/favicon.png b/favicon.png\n" + - "deleted file mode 100644\n" + - "index 2a9d516a5647205d7be510dd0dff93a3663eff6f..0000000000000000000000000000000000000000\n" + - "GIT binary patch\n" + - "literal 0\n" + - "HcmV?d00001\n" + - "\n" + - "literal 471\n" + - "zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ\n" + - "za0`JjqPVOAS4ANVKzqmCp=Cty@U^(7zk!jHsvT~YI{F^=Ex6g|gox78w\n" + - "z+Sn2Du3GS9U7qU`1*NYYlJi3u-!-_B#8k9H0\n" + - "zGl{FnZs<2$wz5^=Q2h-1XI^s{LQL1#T4epqNPC%Orl(tD_@!*EY++~^Lt2<2&!&%=\n" + - "z`m>(TYj6uS7jDdt=eH>iOyQg(QMR<-Fw8)Dk^ZG)XQTuzEgl{`GpS?Cfq9818R9~=\n" + - "z{&h9@9n8F^?|qusoPy{k#%tVHzu7H$t26CR`BJZk*Ixf&u36WuS=?6m2^ho-p00i_\n" + - "I>zopr0Nz-&lmGw#\n" + - "diff --git a/src/test-bar.js b/src/test-baz.js\n" + - "similarity index 98%\n" + - "rename from src/test-bar.js\n" + - "rename to src/test-baz.js\n" + - "index e01513b..f14a870 100644\n" + - "--- a/src/test-bar.js\n" + - "+++ b/src/test-baz.js\n" + - "@@ -1,4 +1,32 @@\n" + - " function foo() {\n" + + 'diff --git a/favicon.png b/favicon.png\n' + + 'deleted file mode 100644\n' + + 'index 2a9d516a5647205d7be510dd0dff93a3663eff6f..0000000000000000000000000000000000000000\n' + + 'GIT binary patch\n' + + 'literal 0\n' + + 'HcmV?d00001\n' + + '\n' + + 'literal 471\n' + + 'zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ\n' + + 'za0`JjqPVOAS4ANVKzqmCp=Cty@U^(7zk!jHsvT~YI{F^=Ex6g|gox78w\n' + + 'z+Sn2Du3GS9U7qU`1*NYYlJi3u-!-_B#8k9H0\n' + + 'zGl{FnZs<2$wz5^=Q2h-1XI^s{LQL1#T4epqNPC%Orl(tD_@!*EY++~^Lt2<2&!&%=\n' + + 'z`m>(TYj6uS7jDdt=eH>iOyQg(QMR<-Fw8)Dk^ZG)XQTuzEgl{`GpS?Cfq9818R9~=\n' + + 'z{&h9@9n8F^?|qusoPy{k#%tVHzu7H$t26CR`BJZk*Ixf&u36WuS=?6m2^ho-p00i_\n' + + 'I>zopr0Nz-&lmGw#\n' + + 'diff --git a/src/test-bar.js b/src/test-baz.js\n' + + 'similarity index 98%\n' + + 'rename from src/test-bar.js\n' + + 'rename to src/test-baz.js\n' + + 'index e01513b..f14a870 100644\n' + + '--- a/src/test-bar.js\n' + + '+++ b/src/test-baz.js\n' + + '@@ -1,4 +1,32 @@\n' + + ' function foo() {\n' + '-var bar = "Whoops!";\n' + '+var baz = "Whoops!";\n' + - " }\n" + - " "; + ' }\n' + + ' '; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ diff --git a/src/__tests__/diff2html-tests.ts b/src/__tests__/diff2html-tests.ts index e813e3d..80784c8 100644 --- a/src/__tests__/diff2html-tests.ts +++ b/src/__tests__/diff2html-tests.ts @@ -1,14 +1,14 @@ -import { parse, html } from "../diff2html"; -import { DiffFile, LineType, OutputFormatType } from "../types"; +import { parse, html } from '../diff2html'; +import { DiffFile, LineType, OutputFormatType } from '../types'; const diffExample1 = - "diff --git a/sample b/sample\n" + - "index 0000001..0ddf2ba\n" + - "--- a/sample\n" + - "+++ b/sample\n" + - "@@ -1 +1 @@\n" + - "-test\n" + - "+test1\n"; + 'diff --git a/sample b/sample\n' + + 'index 0000001..0ddf2ba\n' + + '--- a/sample\n' + + '+++ b/sample\n' + + '@@ -1 +1 @@\n' + + '-test\n' + + '+test1\n'; const jsonExample1: DiffFile[] = [ { @@ -16,47 +16,47 @@ const jsonExample1: DiffFile[] = [ { lines: [ { - content: "-test", + content: '-test', type: LineType.DELETE, oldNumber: 1, - newNumber: undefined + newNumber: undefined, }, { - content: "+test1", + content: '+test1', type: LineType.INSERT, oldNumber: undefined, - newNumber: 1 - } + newNumber: 1, + }, ], oldStartLine: 1, oldStartLine2: undefined, newStartLine: 1, - header: "@@ -1 +1 @@" - } + header: '@@ -1 +1 @@', + }, ], deletedLines: 1, addedLines: 1, - checksumBefore: "0000001", - checksumAfter: "0ddf2ba", - oldName: "sample", - newName: "sample", - language: "", + checksumBefore: '0000001', + checksumAfter: '0ddf2ba', + oldName: 'sample', + newName: 'sample', + language: '', isCombined: false, - isGitDiff: true - } + isGitDiff: true, + }, ]; -describe("Diff2Html", () => { - describe("getJsonFromDiff", () => { - it("should parse simple diff to json", () => { +describe('Diff2Html', () => { + describe('getJsonFromDiff', () => { + it('should parse simple diff to json', () => { const diff = - "diff --git a/sample b/sample\n" + - "index 0000001..0ddf2ba\n" + - "--- a/sample\n" + - "+++ b/sample\n" + - "@@ -1 +1 @@\n" + - "-test\n" + - "+test1\n"; + 'diff --git a/sample b/sample\n' + + 'index 0000001..0ddf2ba\n' + + '--- a/sample\n' + + '+++ b/sample\n' + + '@@ -1 +1 @@\n' + + '-test\n' + + '+test1\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -98,23 +98,23 @@ describe("Diff2Html", () => { }); // Test case for issue #49 - it("should parse diff with added EOF", () => { + it('should parse diff with added EOF', () => { const diff = - "diff --git a/sample.scala b/sample.scala\n" + - "index b583263..8b2fc3e 100644\n" + - "--- a/b583263..8b2fc3e\n" + - "+++ b/8b2fc3e\n" + - "@@ -50,5 +50,7 @@ case class Response[+A](value: Option[A],\n" + - " object ResponseErrorCode extends JsonEnumeration {\n" + - " val NoError, ServiceError, JsonError,\n" + - " InvalidPermissions, MissingPermissions, GenericError,\n" + - "- TokenRevoked, MissingToken = Value\n" + - "-}\n" + - "\\ No newline at end of file\n" + - "+ TokenRevoked, MissingToken,\n" + - "+ IndexLock, RepositoryError, NotValidRepo, PullRequestNotMergeable, BranchError,\n" + - "+ PluginError, CodeParserError, EngineError = Value\n" + - "+}\n"; + 'diff --git a/sample.scala b/sample.scala\n' + + 'index b583263..8b2fc3e 100644\n' + + '--- a/b583263..8b2fc3e\n' + + '+++ b/8b2fc3e\n' + + '@@ -50,5 +50,7 @@ case class Response[+A](value: Option[A],\n' + + ' object ResponseErrorCode extends JsonEnumeration {\n' + + ' val NoError, ServiceError, JsonError,\n' + + ' InvalidPermissions, MissingPermissions, GenericError,\n' + + '- TokenRevoked, MissingToken = Value\n' + + '-}\n' + + '\\ No newline at end of file\n' + + '+ TokenRevoked, MissingToken,\n' + + '+ IndexLock, RepositoryError, NotValidRepo, PullRequestNotMergeable, BranchError,\n' + + '+ PluginError, CodeParserError, EngineError = Value\n' + + '+}\n'; const result = parse(diff); expect(result).toMatchInlineSnapshot(` Array [ @@ -198,7 +198,7 @@ describe("Diff2Html", () => { `); }); - it("should generate pretty line by line html from diff", () => { + it('should generate pretty line by line html from diff', () => { const result = html(diffExample1, { drawFileList: false }); expect(result).toMatchInlineSnapshot(` "
@@ -251,7 +251,7 @@ describe("Diff2Html", () => { `); }); - it("should generate pretty line by line html from json", () => { + it('should generate pretty line by line html from json', () => { const result = html(jsonExample1, { drawFileList: false }); expect(result).toMatchInlineSnapshot(` "
@@ -304,7 +304,7 @@ describe("Diff2Html", () => { `); }); - it("should generate pretty diff with files summary", () => { + it('should generate pretty diff with files summary', () => { const result = html(diffExample1, { drawFileList: true }); expect(result).toMatchInlineSnapshot(` "
@@ -377,7 +377,7 @@ describe("Diff2Html", () => { `); }); - it("should generate pretty side by side html from diff", () => { + it('should generate pretty side by side html from diff', () => { const result = html(diffExample1, { outputFormat: OutputFormatType.SIDE_BY_SIDE, drawFileList: false }); expect(result).toMatchInlineSnapshot(` "
@@ -444,7 +444,7 @@ describe("Diff2Html", () => { `); }); - it("should generate pretty side by side html from json", () => { + it('should generate pretty side by side html from json', () => { const result = html(jsonExample1, { outputFormat: OutputFormatType.SIDE_BY_SIDE, drawFileList: false }); expect(result).toMatchInlineSnapshot(` "
@@ -511,7 +511,7 @@ describe("Diff2Html", () => { `); }); - it("should generate pretty side by side html from diff 2", () => { + it('should generate pretty side by side html from diff 2', () => { const result = html(diffExample1, { outputFormat: OutputFormatType.SIDE_BY_SIDE, drawFileList: true }); expect(result).toMatchInlineSnapshot(` "
@@ -598,30 +598,30 @@ describe("Diff2Html", () => { `); }); - it("should generate pretty side by side html from diff with html on headers", () => { + it('should generate pretty side by side html from diff with html on headers', () => { const diffExample2 = - "diff --git a/CHANGELOG.md b/CHANGELOG.md\n" + - "index fc3e3f4..b486d10 100644\n" + - "--- a/CHANGELOG.md\n" + - "+++ b/CHANGELOG.md\n" + - "@@ -1,7 +1,6 @@\n" + - " # Change Log\n" + - " All notable changes to this project will be documented in this file.\n" + - " This project adheres to [Semantic Versioning](http://semver.org/).\n" + + 'diff --git a/CHANGELOG.md b/CHANGELOG.md\n' + + 'index fc3e3f4..b486d10 100644\n' + + '--- a/CHANGELOG.md\n' + + '+++ b/CHANGELOG.md\n' + + '@@ -1,7 +1,6 @@\n' + + ' # Change Log\n' + + ' All notable changes to this project will be documented in this file.\n' + + ' This project adheres to [Semantic Versioning](http://semver.org/).\n' + '-$a="
Use the following format for additions: ` - VERSION: [feature/patch (if applicable)] Short description of change. Links to relevant issues/PRs.`\n' + ' $a="
\n' + - " $a=\"
- 1.1.9: Fix around ubuntu's inability to cache promises. [#877](https://github.com/FredrikNoren/ungit/pull/878)\n" + - " - 1.1.8:\n" + - "@@ -11,7 +10,7 @@ $a="<table><tr><td>- 1.1.9: Fix around ubuntu's inability to cache promises. [#8\n" + - " - 1.1.7:\n" + - " - Fix diff flickering issue and optimization [#865](https://github.com/FredrikNoren/ungit/pull/865)\n" + - " - Fix credential dialog issue [#864](https://github.com/FredrikNoren/ungit/pull/864)\n" + - "- - Fix HEAD branch order when redraw [#858](https://github.com/FredrikNoren/ungit/issues/858)\n" + - "+4 - Fix HEAD branch order when redraw [#858](https://github.com/FredrikNoren/ungit/issues/858)\n" + - " - 1.1.6: Fix path auto complete [#861](https://github.com/FredrikNoren/ungit/issues/861)\n" + + ' $a=" @@ -20,53 +20,36 @@ describe("HoganJsUtils", () => { `); }); - it("should render view without cache", () => { + it('should throw exception if template is missing', () => { const hoganJsUtils = new HoganJsUtils({}); - const result = hoganJsUtils.render("generic", "empty-diff", { - contentClass: "d2h-code-line", - CSSLineClass: CSSLineClass - }); - expect(result).toMatchInlineSnapshot(` - " - - " - `); + expect(() => hoganJsUtils.render('generic', 'missing-template', {})).toThrow(Error); }); - it("should throw exception if template is missing", () => { - const hoganJsUtils = new HoganJsUtils({}); - expect(() => hoganJsUtils.render("generic", "missing-template", {})).toThrow(Error); - }); + it('should allow templates to be overridden with compiled templates', () => { + const emptyDiffTemplate = HoganJsUtils.compile('

{{myName}}

'); + const hoganJsUtils = new HoganJsUtils({ compiledTemplates: { 'generic-empty-diff': emptyDiffTemplate } }); - it("should allow templates to be overridden with compiled templates", () => { - const emptyDiffTemplate = HoganJsUtils.compile("

{{myName}}

"); - const hoganJsUtils = new HoganJsUtils({ compiledTemplates: { "generic-empty-diff": emptyDiffTemplate } }); - - const result = hoganJsUtils.render("generic", "empty-diff", { myName: "Rodrigo Fernandes" }); + const result = hoganJsUtils.render('generic', 'empty-diff', { myName: 'Rodrigo Fernandes' }); expect(result).toMatchInlineSnapshot(`"

Rodrigo Fernandes

"`); }); - it("should allow templates to be overridden with uncompiled templates", () => { - const emptyDiffTemplate = "

{{myName}}

"; - const hoganJsUtils = new HoganJsUtils({ rawTemplates: { "generic-empty-diff": emptyDiffTemplate } }); + it('should allow templates to be overridden with uncompiled templates', () => { + const emptyDiffTemplate = '

{{myName}}

'; + const hoganJsUtils = new HoganJsUtils({ rawTemplates: { 'generic-empty-diff': emptyDiffTemplate } }); - const result = hoganJsUtils.render("generic", "empty-diff", { myName: "Rodrigo Fernandes" }); + const result = hoganJsUtils.render('generic', 'empty-diff', { myName: 'Rodrigo Fernandes' }); expect(result).toMatchInlineSnapshot(`"

Rodrigo Fernandes

"`); }); - it("should allow templates to be overridden giving priority to raw templates", () => { - const emptyDiffTemplate = HoganJsUtils.compile("

Not used!

"); - const emptyDiffTemplateUncompiled = "

{{myName}}

"; + it('should allow templates to be overridden giving priority to raw templates', () => { + const emptyDiffTemplate = HoganJsUtils.compile('

Not used!

'); + const emptyDiffTemplateUncompiled = '

{{myName}}

'; const hoganJsUtils = new HoganJsUtils({ - compiledTemplates: { "generic-empty-diff": emptyDiffTemplate }, - rawTemplates: { "generic-empty-diff": emptyDiffTemplateUncompiled } + compiledTemplates: { 'generic-empty-diff': emptyDiffTemplate }, + rawTemplates: { 'generic-empty-diff': emptyDiffTemplateUncompiled }, }); - const result = hoganJsUtils.render("generic", "empty-diff", { myName: "Rodrigo Fernandes" }); + const result = hoganJsUtils.render('generic', 'empty-diff', { myName: 'Rodrigo Fernandes' }); expect(result).toMatchInlineSnapshot(`"

Rodrigo Fernandes

"`); }); }); diff --git a/src/__tests__/line-by-line-tests.ts b/src/__tests__/line-by-line-tests.ts index f33b904..b210dbf 100644 --- a/src/__tests__/line-by-line-tests.ts +++ b/src/__tests__/line-by-line-tests.ts @@ -1,11 +1,11 @@ -import LineByLineRenderer from "../line-by-line-renderer"; -import HoganJsUtils from "../hoganjs-utils"; -import { LineType, DiffFile, LineMatchingType } from "../types"; -import { CSSLineClass } from "../render-utils"; +import LineByLineRenderer from '../line-by-line-renderer'; +import HoganJsUtils from '../hoganjs-utils'; +import { LineType, DiffFile, LineMatchingType } from '../types'; +import { CSSLineClass } from '../render-utils'; -describe("LineByLineRenderer", () => { - describe("_generateEmptyDiff", () => { - it("should return an empty diff", () => { +describe('LineByLineRenderer', () => { + describe('_generateEmptyDiff', () => { + it('should return an empty diff', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const fileHtml = lineByLineRenderer.generateEmptyDiff(); @@ -21,16 +21,16 @@ describe("LineByLineRenderer", () => { }); }); - describe("makeLineHtml", () => { - it("should work for insertions", () => { + describe('makeLineHtml', () => { + it('should work for insertions', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const fileHtml = lineByLineRenderer.generateSingleLineHtml({ type: CSSLineClass.INSERTS, - prefix: "+", - content: "test", + prefix: '+', + content: 'test', oldNumber: undefined, - newNumber: 30 + newNumber: 30, }); expect(fileHtml).toMatchInlineSnapshot(` " @@ -48,15 +48,15 @@ describe("LineByLineRenderer", () => { `); }); - it("should work for deletions", () => { + it('should work for deletions', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const fileHtml = lineByLineRenderer.generateSingleLineHtml({ type: CSSLineClass.DELETES, - prefix: "-", - content: "test", + prefix: '-', + content: 'test', oldNumber: 30, - newNumber: undefined + newNumber: undefined, }); expect(fileHtml).toMatchInlineSnapshot(` " @@ -74,15 +74,15 @@ describe("LineByLineRenderer", () => { `); }); - it("should convert indents into non breakin spaces (2 white spaces)", () => { + it('should convert indents into non breakin spaces (2 white spaces)', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const fileHtml = lineByLineRenderer.generateSingleLineHtml({ type: CSSLineClass.INSERTS, - prefix: "+", - content: " test", + prefix: '+', + content: ' test', oldNumber: undefined, - newNumber: 30 + newNumber: 30, }); expect(fileHtml).toMatchInlineSnapshot(` " @@ -100,15 +100,15 @@ describe("LineByLineRenderer", () => { `); }); - it("should convert indents into non breakin spaces (4 white spaces)", () => { + it('should convert indents into non breakin spaces (4 white spaces)', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const fileHtml = lineByLineRenderer.generateSingleLineHtml({ type: CSSLineClass.INSERTS, - prefix: "+", - content: " test", + prefix: '+', + content: ' test', oldNumber: undefined, - newNumber: 30 + newNumber: 30, }); expect(fileHtml).toMatchInlineSnapshot(` " @@ -126,15 +126,15 @@ describe("LineByLineRenderer", () => { `); }); - it("should preserve tabs", () => { + it('should preserve tabs', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const fileHtml = lineByLineRenderer.generateSingleLineHtml({ type: CSSLineClass.INSERTS, - prefix: "+", - content: "\ttest", + prefix: '+', + content: '\ttest', oldNumber: undefined, - newNumber: 30 + newNumber: 30, }); expect(fileHtml).toMatchInlineSnapshot(` " @@ -153,22 +153,22 @@ describe("LineByLineRenderer", () => { }); }); - describe("makeFileDiffHtml", () => { - it("should work for simple file", () => { + describe('makeFileDiffHtml', () => { + it('should work for simple file', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const file = { addedLines: 12, deletedLines: 41, - language: "js", - oldName: "my/file/name.js", - newName: "my/file/name.js", + language: 'js', + oldName: 'my/file/name.js', + newName: 'my/file/name.js', isCombined: false, isGitDiff: false, - blocks: [] + blocks: [], }; - const diffs = "Random Html"; + const diffs = 'Random Html'; const fileHtml = lineByLineRenderer.makeFileDiffHtml(file, diffs); @@ -193,22 +193,22 @@ describe("LineByLineRenderer", () => { " `); }); - it("should work for simple added file", () => { + it('should work for simple added file', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const file = { addedLines: 12, deletedLines: 0, - language: "js", - oldName: "dev/null", - newName: "my/file/name.js", + language: 'js', + oldName: 'dev/null', + newName: 'my/file/name.js', isNew: true, isCombined: false, isGitDiff: false, - blocks: [] + blocks: [], }; - const diffs = "Random Html"; + const diffs = 'Random Html'; const fileHtml = lineByLineRenderer.makeFileDiffHtml(file, diffs); @@ -233,22 +233,22 @@ describe("LineByLineRenderer", () => { " `); }); - it("should work for simple deleted file", () => { + it('should work for simple deleted file', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const file = { addedLines: 0, deletedLines: 41, - language: "js", - oldName: "my/file/name.js", - newName: "dev/null", + language: 'js', + oldName: 'my/file/name.js', + newName: 'dev/null', isDeleted: true, isCombined: false, isGitDiff: false, - blocks: [] + blocks: [], }; - const diffs = "Random Html"; + const diffs = 'Random Html'; const fileHtml = lineByLineRenderer.makeFileDiffHtml(file, diffs); @@ -273,22 +273,22 @@ describe("LineByLineRenderer", () => { " `); }); - it("should work for simple renamed file", () => { + it('should work for simple renamed file', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const file = { addedLines: 12, deletedLines: 41, - language: "js", - oldName: "my/file/name1.js", - newName: "my/file/name2.js", + language: 'js', + oldName: 'my/file/name1.js', + newName: 'my/file/name2.js', isRename: true, isCombined: false, isGitDiff: false, - blocks: [] + blocks: [], }; - const diffs = "Random Html"; + const diffs = 'Random Html'; const fileHtml = lineByLineRenderer.makeFileDiffHtml(file, diffs); @@ -313,25 +313,25 @@ describe("LineByLineRenderer", () => { " `); }); - it("should return empty when option renderNothingWhenEmpty is true and file blocks not present", () => { + it('should return empty when option renderNothingWhenEmpty is true and file blocks not present', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, { - renderNothingWhenEmpty: true + renderNothingWhenEmpty: true, }); const file = { addedLines: 0, deletedLines: 0, - language: "js", - oldName: "my/file/name1.js", - newName: "my/file/name2.js", + language: 'js', + oldName: 'my/file/name1.js', + newName: 'my/file/name2.js', isRename: true, isCombined: false, isGitDiff: false, - blocks: [] + blocks: [], }; - const diffs = "Random Html"; + const diffs = 'Random Html'; const fileHtml = lineByLineRenderer.makeFileDiffHtml(file, diffs); @@ -339,47 +339,47 @@ describe("LineByLineRenderer", () => { }); }); - describe("generateLineByLineJsonHtml", () => { - it("should work for list of files", () => { + describe('generateLineByLineJsonHtml', () => { + it('should work for list of files', () => { const exampleJson: DiffFile[] = [ { blocks: [ { lines: [ { - content: "-test", + content: '-test', type: LineType.DELETE, oldNumber: 1, - newNumber: undefined + newNumber: undefined, }, { - content: "+test1r", + content: '+test1r', type: LineType.INSERT, oldNumber: undefined, - newNumber: 1 - } + newNumber: 1, + }, ], oldStartLine: 1, oldStartLine2: undefined, newStartLine: 1, - header: "@@ -1 +1 @@" - } + header: '@@ -1 +1 @@', + }, ], deletedLines: 1, addedLines: 1, - checksumBefore: "0000001", - checksumAfter: "0ddf2ba", - oldName: "sample", - newName: "sample", - language: "txt", + checksumBefore: '0000001', + checksumAfter: '0ddf2ba', + oldName: 'sample', + newName: 'sample', + language: 'txt', isCombined: false, - isGitDiff: true - } + isGitDiff: true, + }, ]; const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, { - matching: LineMatchingType.LINES + matching: LineMatchingType.LINES, }); const html = lineByLineRenderer.render(exampleJson); expect(html).toMatchInlineSnapshot(` @@ -433,23 +433,23 @@ describe("LineByLineRenderer", () => { `); }); - it("should work for empty blocks", () => { + it('should work for empty blocks', () => { const exampleJson = [ { blocks: [], deletedLines: 0, addedLines: 0, - oldName: "sample", - language: "js", - newName: "sample", + oldName: 'sample', + language: 'js', + newName: 'sample', isCombined: false, - isGitDiff: false - } + isGitDiff: false, + }, ]; const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, { - renderNothingWhenEmpty: false + renderNothingWhenEmpty: false, }); const html = lineByLineRenderer.render(exampleJson); expect(html).toMatchInlineSnapshot(` @@ -483,8 +483,8 @@ describe("LineByLineRenderer", () => { }); }); - describe("_generateFileHtml", () => { - it("should work for simple file", () => { + describe('_generateFileHtml', () => { + it('should work for simple file', () => { const hoganUtils = new HoganJsUtils({}); const lineByLineRenderer = new LineByLineRenderer(hoganUtils, {}); const file: DiffFile = { @@ -492,45 +492,45 @@ describe("LineByLineRenderer", () => { { lines: [ { - content: " one context line", + content: ' one context line', type: LineType.CONTEXT, oldNumber: 1, - newNumber: 1 + newNumber: 1, }, { - content: "-test", + content: '-test', type: LineType.DELETE, oldNumber: 2, - newNumber: undefined + newNumber: undefined, }, { - content: "+test1r", + content: '+test1r', type: LineType.INSERT, oldNumber: undefined, - newNumber: 2 + newNumber: 2, }, { - content: "+test2r", + content: '+test2r', type: LineType.INSERT, oldNumber: undefined, - newNumber: 3 - } + newNumber: 3, + }, ], oldStartLine: 1, oldStartLine2: undefined, newStartLine: 1, - header: "@@ -1 +1 @@" - } + header: '@@ -1 +1 @@', + }, ], deletedLines: 1, addedLines: 1, - checksumBefore: "0000001", - checksumAfter: "0ddf2ba", - oldName: "sample", - language: "txt", - newName: "sample", + checksumBefore: '0000001', + checksumAfter: '0ddf2ba', + oldName: 'sample', + language: 'txt', + newName: 'sample', isCombined: false, - isGitDiff: true + isGitDiff: true, }; const html = lineByLineRenderer.generateFileHtml(file); diff --git a/src/__tests__/printer-utils-tests.ts b/src/__tests__/printer-utils-tests.ts index cc2847c..0341edd 100644 --- a/src/__tests__/printer-utils-tests.ts +++ b/src/__tests__/printer-utils-tests.ts @@ -1,158 +1,151 @@ -import { escapeForHtml, getHtmlId, filenameDiff, diffHighlight } from "../render-utils"; -import { DiffStyleType, LineMatchingType } from "../types"; +import { escapeForHtml, getHtmlId, filenameDiff, diffHighlight } from '../render-utils'; +import { DiffStyleType, LineMatchingType } from '../types'; -describe("Utils", () => { - describe("escapeForHtml", () => { - it("should escape & with &", () => { - const result = escapeForHtml("&"); - expect(result).toEqual("&"); +describe('Utils', () => { + describe('escapeForHtml', () => { + it('should escape & with &', () => { + const result = escapeForHtml('&'); + expect(result).toEqual('&'); }); - it("should escape < with <", () => { - const result = escapeForHtml("<"); - expect(result).toEqual("<"); + it('should escape < with <', () => { + const result = escapeForHtml('<'); + expect(result).toEqual('<'); }); - it("should escape > with >", () => { - const result = escapeForHtml(">"); - expect(result).toEqual(">"); + it('should escape > with >', () => { + const result = escapeForHtml('>'); + expect(result).toEqual('>'); }); it('should escape " with "', () => { const result = escapeForHtml('"'); - expect(result).toEqual("""); + expect(result).toEqual('"'); }); it("should escape ' with '", () => { const result = escapeForHtml("'"); - expect(result).toEqual("'"); + expect(result).toEqual('''); }); - it("should escape / with /", () => { - const result = escapeForHtml("/"); - expect(result).toEqual("/"); + it('should escape / with /', () => { + const result = escapeForHtml('/'); + expect(result).toEqual('/'); }); - it("should escape a string containing HTML code", () => { + it('should escape a string containing HTML code', () => { const result = escapeForHtml(`Search 'Diff2Html'`); expect(result).toEqual( - "<a href="/search?q=diff2html">Search 'Diff2Html'</a>" + '<a href="/search?q=diff2html">Search 'Diff2Html'</a>', ); }); }); - describe("getHtmlId", () => { - it("should generate file unique id", () => { + describe('getHtmlId', () => { + it('should generate file unique id', () => { const result = getHtmlId({ - oldName: "sample.js", - newName: "sample.js" + oldName: 'sample.js', + newName: 'sample.js', }); - expect(result).toEqual("d2h-960013"); - }); - it("should generate file unique id for empty hashes", () => { - const result = getHtmlId({ - oldName: "sample.js", - newName: "sample.js" - }); - expect(result).toEqual("d2h-960013"); + expect(result).toEqual('d2h-960013'); }); }); - describe("getDiffName", () => { - it("should generate the file name for a changed file", () => { + describe('getDiffName', () => { + it('should generate the file name for a changed file', () => { const result = filenameDiff({ - oldName: "sample.js", - newName: "sample.js" + oldName: 'sample.js', + newName: 'sample.js', }); - expect(result).toEqual("sample.js"); + expect(result).toEqual('sample.js'); }); - it("should generate the file name for a changed file and full rename", () => { + it('should generate the file name for a changed file and full rename', () => { const result = filenameDiff({ - oldName: "sample1.js", - newName: "sample2.js" + oldName: 'sample1.js', + newName: 'sample2.js', }); - expect(result).toEqual("sample1.js → sample2.js"); + expect(result).toEqual('sample1.js → sample2.js'); }); - it("should generate the file name for a changed file and prefix rename", () => { + it('should generate the file name for a changed file and prefix rename', () => { const result = filenameDiff({ - oldName: "src/path/sample.js", - newName: "source/path/sample.js" + oldName: 'src/path/sample.js', + newName: 'source/path/sample.js', }); - expect(result).toEqual("{src → source}/path/sample.js"); + expect(result).toEqual('{src → source}/path/sample.js'); }); - it("should generate the file name for a changed file and suffix rename", () => { + it('should generate the file name for a changed file and suffix rename', () => { const result = filenameDiff({ - oldName: "src/path/sample1.js", - newName: "src/path/sample2.js" + oldName: 'src/path/sample1.js', + newName: 'src/path/sample2.js', }); - expect(result).toEqual("src/path/{sample1.js → sample2.js}"); + expect(result).toEqual('src/path/{sample1.js → sample2.js}'); }); - it("should generate the file name for a changed file and middle rename", () => { + it('should generate the file name for a changed file and middle rename', () => { const result = filenameDiff({ - oldName: "src/really/big/path/sample.js", - newName: "src/small/path/sample.js" + oldName: 'src/really/big/path/sample.js', + newName: 'src/small/path/sample.js', }); - expect(result).toEqual("src/{really/big → small}/path/sample.js"); + expect(result).toEqual('src/{really/big → small}/path/sample.js'); }); - it("should generate the file name for a deleted file", () => { + it('should generate the file name for a deleted file', () => { const result = filenameDiff({ - oldName: "src/my/file.js", - newName: "/dev/null" + oldName: 'src/my/file.js', + newName: '/dev/null', }); - expect(result).toEqual("src/my/file.js"); + expect(result).toEqual('src/my/file.js'); }); - it("should generate the file name for a new file", () => { + it('should generate the file name for a new file', () => { const result = filenameDiff({ - oldName: "/dev/null", - newName: "src/my/file.js" + oldName: '/dev/null', + newName: 'src/my/file.js', }); - expect(result).toEqual("src/my/file.js"); + expect(result).toEqual('src/my/file.js'); }); }); - describe("diffHighlight", () => { - it("should highlight two lines", () => { - const result = diffHighlight("-var myVar = 2;", "+var myVariable = 3;", false, { - matching: LineMatchingType.WORDS + describe('diffHighlight', () => { + it('should highlight two lines', () => { + const result = diffHighlight('-var myVar = 2;', '+var myVariable = 3;', false, { + matching: LineMatchingType.WORDS, }); expect(result).toEqual({ oldLine: { - prefix: "-", - content: "var myVar = 2;" + prefix: '-', + content: 'var myVar = 2;', }, newLine: { - prefix: "+", - content: "var myVariable = 3;" - } + prefix: '+', + content: 'var myVariable = 3;', + }, }); }); - it("should highlight two lines char by char", () => { - const result = diffHighlight("-var myVar = 2;", "+var myVariable = 3;", false, { - diffStyle: DiffStyleType.CHAR + it('should highlight two lines char by char', () => { + const result = diffHighlight('-var myVar = 2;', '+var myVariable = 3;', false, { + diffStyle: DiffStyleType.CHAR, }); expect(result).toEqual({ oldLine: { - prefix: "-", - content: "var myVar = 2;" + prefix: '-', + content: 'var myVar = 2;', }, newLine: { - prefix: "+", - content: "var myVariable = 3;" - } + prefix: '+', + content: 'var myVariable = 3;', + }, }); }); - it("should highlight combined diff lines", () => { - const result = diffHighlight(" -var myVar = 2;", " +var myVariable = 3;", true, { + it('should highlight combined diff lines', () => { + const result = diffHighlight(' -var myVar = 2;', ' +var myVariable = 3;', true, { diffStyle: DiffStyleType.WORD, matching: LineMatchingType.WORDS, - matchWordsThreshold: 1.0 + matchWordsThreshold: 1.0, }); expect(result).toEqual({ oldLine: { - prefix: " -", - content: 'var myVar = 2;' + prefix: ' -', + content: 'var myVar = 2;', }, newLine: { - prefix: " +", - content: 'var myVariable = 3;' - } + prefix: ' +', + content: 'var myVariable = 3;', + }, }); }); }); diff --git a/src/__tests__/side-by-side-printer-tests.ts b/src/__tests__/side-by-side-printer-tests.ts index e9c7ac7..9e1a7c0 100644 --- a/src/__tests__/side-by-side-printer-tests.ts +++ b/src/__tests__/side-by-side-printer-tests.ts @@ -1,11 +1,11 @@ -import SideBySideRenderer from "../side-by-side-renderer"; -import HoganJsUtils from "../hoganjs-utils"; -import { LineType, DiffLine, DiffFile, LineMatchingType } from "../types"; -import { CSSLineClass } from "../render-utils"; +import SideBySideRenderer from '../side-by-side-renderer'; +import HoganJsUtils from '../hoganjs-utils'; +import { LineType, DiffLine, DiffFile, LineMatchingType } from '../types'; +import { CSSLineClass } from '../render-utils'; -describe("SideBySideRenderer", () => { - describe("generateEmptyDiff", () => { - it("should return an empty diff", () => { +describe('SideBySideRenderer', () => { + describe('generateEmptyDiff', () => { + it('should return an empty diff', () => { const hoganUtils = new HoganJsUtils({}); const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {}); const fileHtml = sideBySideRenderer.generateEmptyDiff(); @@ -24,8 +24,8 @@ describe("SideBySideRenderer", () => { }); }); - describe("generateSideBySideFileHtml", () => { - it("should generate lines with the right prefixes", () => { + describe('generateSideBySideFileHtml', () => { + it('should generate lines with the right prefixes', () => { const hoganUtils = new HoganJsUtils({}); const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {}); @@ -35,44 +35,44 @@ describe("SideBySideRenderer", () => { { lines: [ { - content: " context", + content: ' context', type: LineType.CONTEXT, oldNumber: 19, - newNumber: 19 + newNumber: 19, }, { - content: "-removed", + content: '-removed', type: LineType.DELETE, oldNumber: 20, - newNumber: undefined + newNumber: undefined, }, { - content: "+added", + content: '+added', type: LineType.INSERT, oldNumber: undefined, - newNumber: 20 + newNumber: 20, }, { - content: "+another added", + content: '+another added', type: LineType.INSERT, oldNumber: undefined, - newNumber: 21 - } + newNumber: 21, + }, ], oldStartLine: 19, newStartLine: 19, - header: "@@ -19,7 +19,7 @@" - } + header: '@@ -19,7 +19,7 @@', + }, ], deletedLines: 1, addedLines: 2, - checksumBefore: "fc56817", - checksumAfter: "e8e7e49", - mode: "100644", - oldName: "coverage.init", - language: "init", - newName: "coverage.init", - isCombined: false + checksumBefore: 'fc56817', + checksumAfter: 'e8e7e49', + mode: '100644', + oldName: 'coverage.init', + language: 'init', + newName: 'coverage.init', + isCombined: false, }; const fileHtml = sideBySideRenderer.generateFileHtml(file); @@ -156,15 +156,15 @@ describe("SideBySideRenderer", () => { }); }); - describe("generateSingleLineHtml", () => { - it("should work for insertions", () => { + describe('generateSingleLineHtml', () => { + it('should work for insertions', () => { const hoganUtils = new HoganJsUtils({}); const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {}); const fileHtml = sideBySideRenderer.generateLineHtml(undefined, { type: CSSLineClass.INSERTS, - prefix: "+", - content: "test", - number: 30 + prefix: '+', + content: 'test', + number: 30, }); expect(fileHtml).toMatchInlineSnapshot(` @@ -194,17 +194,17 @@ describe("SideBySideRenderer", () => { } `); }); - it("should work for deletions", () => { + it('should work for deletions', () => { const hoganUtils = new HoganJsUtils({}); const sideBySideRenderer = new SideBySideRenderer(hoganUtils, {}); const fileHtml = sideBySideRenderer.generateLineHtml( { type: CSSLineClass.DELETES, - prefix: "-", - content: "test", - number: 30 + prefix: '-', + content: 'test', + number: 30, }, - undefined + undefined, ); expect(fileHtml).toMatchInlineSnapshot(` @@ -236,42 +236,42 @@ describe("SideBySideRenderer", () => { }); }); - describe("generateSideBySideJsonHtml", () => { - it("should work for list of files", () => { + describe('generateSideBySideJsonHtml', () => { + it('should work for list of files', () => { const exampleJson: DiffFile[] = [ { blocks: [ { lines: [ { - content: "-test", + content: '-test', type: LineType.DELETE, oldNumber: 1, - newNumber: undefined + newNumber: undefined, }, { - content: "+test1r", + content: '+test1r', type: LineType.INSERT, oldNumber: undefined, - newNumber: 1 - } + newNumber: 1, + }, ], oldStartLine: 1, oldStartLine2: undefined, newStartLine: 1, - header: "@@ -1 +1 @@" - } + header: '@@ -1 +1 @@', + }, ], deletedLines: 1, addedLines: 1, - checksumBefore: "0000001", - checksumAfter: "0ddf2ba", - oldName: "sample", - language: "txt", - newName: "sample", + checksumBefore: '0000001', + checksumAfter: '0ddf2ba', + oldName: 'sample', + language: 'txt', + newName: 'sample', isCombined: false, - isGitDiff: true - } + isGitDiff: true, + }, ]; const hoganUtils = new HoganJsUtils({}); @@ -341,18 +341,18 @@ describe("SideBySideRenderer", () => { " `); }); - it("should work for files without blocks", () => { + it('should work for files without blocks', () => { const exampleJson: DiffFile[] = [ { blocks: [], - oldName: "sample", - language: "js", - newName: "sample", + oldName: 'sample', + language: 'js', + newName: 'sample', isCombined: false, addedLines: 0, deletedLines: 0, - isGitDiff: false - } + isGitDiff: false, + }, ]; const hoganUtils = new HoganJsUtils({}); @@ -400,24 +400,24 @@ describe("SideBySideRenderer", () => { }); }); - describe("processLines", () => { - it("should process file lines", () => { + describe('processLines', () => { + it('should process file lines', () => { const oldLines: DiffLine[] = [ { - content: "-test", + content: '-test', type: LineType.DELETE, oldNumber: 1, - newNumber: undefined - } + newNumber: undefined, + }, ]; const newLines: DiffLine[] = [ { - content: "+test1r", + content: '+test1r', type: LineType.INSERT, oldNumber: undefined, - newNumber: 1 - } + newNumber: 1, + }, ]; const hoganUtils = new HoganJsUtils({}); diff --git a/src/__tests__/utils-tests.ts b/src/__tests__/utils-tests.ts index 9023c26..1c7c650 100644 --- a/src/__tests__/utils-tests.ts +++ b/src/__tests__/utils-tests.ts @@ -1,31 +1,31 @@ -import { escapeForRegExp, unifyPath, hashCode } from "../utils"; +import { escapeForRegExp, unifyPath, hashCode } from '../utils'; -describe("Utils", () => { - describe("escapeForRegExp", () => { - it("should escape markdown link text", () => { - const result = escapeForRegExp("[Link](https://diff2html.xyz)"); - expect(result).toEqual("\\[Link\\]\\(https:\\/\\/diff2html\\.xyz\\)"); +describe('Utils', () => { + describe('escapeForRegExp', () => { + it('should escape markdown link text', () => { + const result = escapeForRegExp('[Link](https://diff2html.xyz)'); + expect(result).toEqual('\\[Link\\]\\(https:\\/\\/diff2html\\.xyz\\)'); }); - it("should escape all dangerous characters", () => { - const result = escapeForRegExp("-[]/{}()*+?.\\^$|"); - expect(result).toEqual("\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|"); + it('should escape all dangerous characters', () => { + const result = escapeForRegExp('-[]/{}()*+?.\\^$|'); + expect(result).toEqual('\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|'); }); }); - describe("unifyPath", () => { - it("should unify windows style path", () => { - const result = unifyPath("\\Users\\Downloads\\diff.html"); - expect(result).toEqual("/Users/Downloads/diff.html"); + describe('unifyPath', () => { + it('should unify windows style path', () => { + const result = unifyPath('\\Users\\Downloads\\diff.html'); + expect(result).toEqual('/Users/Downloads/diff.html'); }); }); - describe("hashCode", () => { - it("should create consistent hash for a text piece", () => { - const string = "/home/diff2html/diff.html"; + describe('hashCode', () => { + it('should create consistent hash for a text piece', () => { + const string = '/home/diff2html/diff.html'; expect(hashCode(string)).toEqual(hashCode(string)); }); - it("should create different hash for different text pieces", () => { - expect(hashCode("/home/diff2html/diff1.html")).not.toEqual(hashCode("/home/diff2html/diff2.html")); + it('should create different hash for different text pieces', () => { + expect(hashCode('/home/diff2html/diff1.html')).not.toEqual(hashCode('/home/diff2html/diff2.html')); }); }); }); diff --git a/src/diff-parser.ts b/src/diff-parser.ts index 7a5fc5d..bd92420 100644 --- a/src/diff-parser.ts +++ b/src/diff-parser.ts @@ -1,5 +1,5 @@ -import { DiffFile, DiffBlock, DiffLine, LineType } from "./types"; -import { escapeForRegExp } from "./utils"; +import { DiffFile, DiffBlock, DiffLine, LineType } from './types'; +import { escapeForRegExp } from './utils'; export interface DiffParserConfig { srcPrefix?: string; @@ -7,7 +7,7 @@ export interface DiffParserConfig { } function getExtension(filename: string, language: string): string { - const filenameParts = filename.split("."); + const filenameParts = filename.split('.'); return filenameParts.length > 1 ? filenameParts[filenameParts.length - 1] : language; } @@ -15,7 +15,7 @@ function startsWithAny(str: string, prefixes: string[]): boolean { return prefixes.reduce((startsWith, prefix) => startsWith || str.startsWith(prefix), false); } -const baseDiffFilenamePrefixes = ["a/", "b/", "i/", "w/", "c/", "o/"]; +const baseDiffFilenamePrefixes = ['a/', 'b/', 'i/', 'w/', 'c/', 'o/']; function getFilename(line: string, linePrefix?: string, extraPrefix?: string): string { const prefixes = extraPrefix !== undefined ? [...baseDiffFilenamePrefixes, extraPrefix] : baseDiffFilenamePrefixes; @@ -23,22 +23,22 @@ function getFilename(line: string, linePrefix?: string, extraPrefix?: string): s ? new RegExp(`^${escapeForRegExp(linePrefix)} "?(.+?)"?$`) : new RegExp('^"?(.+?)"?$'); - const [, filename = ""] = FilenameRegExp.exec(line) || []; + const [, filename = ''] = FilenameRegExp.exec(line) || []; const matchingPrefix = prefixes.find(p => filename.indexOf(p) === 0); const fnameWithoutPrefix = matchingPrefix ? filename.slice(matchingPrefix.length) : filename; // Cleanup timestamps generated by the unified diff (diff command) as specified in // https://www.gnu.org/software/diffutils/manual/html_node/Detailed-Unified.html // Ie: 2016-10-25 11:37:14.000000000 +0200 - return fnameWithoutPrefix.replace(/\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)? [-+]\d{4}.*$/, ""); + return fnameWithoutPrefix.replace(/\s+\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)? [+-]\d{4}.*$/, ''); } function getSrcFilename(line: string, srcPrefix?: string): string | undefined { - return getFilename(line, "---", srcPrefix); + return getFilename(line, '---', srcPrefix); } function getDstFilename(line: string, dstPrefix?: string): string | undefined { - return getFilename(line, "+++", dstPrefix); + return getFilename(line, '+++', dstPrefix); } /** @@ -61,9 +61,9 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil let possibleNewName: string | null = null; /* Diff Header */ - const oldFileNameHeader = "--- "; - const newFileNameHeader = "+++ "; - const hunkHeaderPrefix = "@@"; + const oldFileNameHeader = '--- '; + const newFileNameHeader = '+++ '; + const hunkHeaderPrefix = '@@'; /* Diff */ const oldMode = /^old mode (\d{6})/; @@ -79,21 +79,21 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil const similarityIndex = /^similarity index (\d+)%/; const dissimilarityIndex = /^dissimilarity index (\d+)%/; - const index = /^index ([0-9a-z]+)\.\.([0-9a-z]+)\s*(\d{6})?/; + const index = /^index ([\da-z]+)\.\.([\da-z]+)\s*(\d{6})?/; const binaryFiles = /^Binary files (.*) and (.*) differ/; const binaryDiff = /^GIT binary patch/; /* Combined Diff */ - const combinedIndex = /^index ([0-9a-z]+),([0-9a-z]+)\.\.([0-9a-z]+)/; + const combinedIndex = /^index ([\da-z]+),([\da-z]+)\.\.([\da-z]+)/; const combinedMode = /^mode (\d{6}),(\d{6})\.\.(\d{6})/; const combinedNewFile = /^new file mode (\d{6})/; const combinedDeletedFile = /^deleted file mode (\d{6}),(\d{6})/; const diffLines = diffInput - .replace(/\\ No newline at end of file/g, "") - .replace(/\r\n?/g, "\n") - .split("\n"); + .replace(/\\ No newline at end of file/g, '') + .replace(/\r\n?/g, '\n') + .split('\n'); /* Add previous block(if exists) before start a new file */ function saveBlock(): void { @@ -137,7 +137,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil currentFile = { blocks: [], deletedLines: 0, - addedLines: 0 + addedLines: 0, }; } @@ -172,7 +172,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil newLine = parseInt(values[3], 10); } else { if (line.startsWith(hunkHeaderPrefix)) { - console.error("Failed to parse lines, starting in 0!"); + console.error('Failed to parse lines, starting in 0!'); } oldLine = 0; @@ -189,7 +189,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil oldStartLine: oldLine, oldStartLine2: oldLine2, newStartLine: newLine, - header: line + header: line, }; } @@ -199,11 +199,11 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil // eslint-disable-next-line // @ts-ignore const currentLine: DiffLine = { - content: line + content: line, }; - const addedPrefixes = currentFile.isCombined ? ["+ ", " +", "++"] : ["+"]; - const deletedPrefixes = currentFile.isCombined ? ["- ", " -", "--"] : ["-"]; + const addedPrefixes = currentFile.isCombined ? ['+ ', ' +', '++'] : ['+']; + const deletedPrefixes = currentFile.isCombined ? ['- ', ' -', '--'] : ['-']; if (startsWithAny(line, addedPrefixes)) { currentFile.addedLines++; @@ -232,7 +232,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil let idx = lineIdx; while (idx < diffLines.length - 3) { - if (line.startsWith("diff")) { + if (line.startsWith('diff')) { return false; } @@ -254,7 +254,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil // Unmerged paths, and possibly other non-diffable files // https://github.com/scottgonzalez/pretty-diff/issues/11 // Also, remove some useless lines - if (!line || line.startsWith("*")) { + if (!line || line.startsWith('*')) { return; } @@ -265,7 +265,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil const nxtLine = diffLines[lineIndex + 1]; const afterNxtLine = diffLines[lineIndex + 2]; - if (line.startsWith("diff")) { + if (line.startsWith('diff')) { startFile(); // diff --git a/blocked_delta_results.png b/blocked_delta_results.png @@ -276,7 +276,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil } if (currentFile === null) { - throw new Error("Where is my file !!!"); + throw new Error('Where is my file !!!'); } currentFile.isGitDiff = true; @@ -311,7 +311,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil if ( currentFile && !currentFile.oldName && - line.startsWith("--- ") && + line.startsWith('--- ') && (values = getSrcFilename(line, config.srcPrefix)) ) { currentFile.oldName = values; @@ -326,7 +326,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil if ( currentFile && !currentFile.newName && - line.startsWith("+++ ") && + line.startsWith('+++ ') && (values = getDstFilename(line, config.dstPrefix)) ) { currentFile.newName = values; @@ -350,7 +350,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil * 2. Old line starts with: - * 3. Context line starts with: */ - if (currentBlock && (line.startsWith("+") || line.startsWith("-") || line.startsWith(" "))) { + if (currentBlock && (line.startsWith('+') || line.startsWith('-') || line.startsWith(' '))) { createLine(line); return; } @@ -358,7 +358,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil const doesNotExistHunkHeader = !existHunkHeader(line, lineIndex); if (currentFile === null) { - throw new Error("Where is my file !!!"); + throw new Error('Where is my file !!!'); } /* @@ -399,7 +399,7 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil currentFile.isBinary = true; currentFile.oldName = getFilename(values[1], undefined, config.srcPrefix); currentFile.newName = getFilename(values[2], undefined, config.dstPrefix); - startBlock("Binary file"); + startBlock('Binary file'); } else if (binaryDiff.test(line)) { currentFile.isBinary = true; startBlock(line); @@ -417,9 +417,11 @@ export function parse(diffInput: string, config: DiffParserConfig = {}): DiffFil } else if ((values = combinedMode.exec(line))) { currentFile.oldMode = [values[2], values[3]]; currentFile.newMode = values[1]; + // eslint-disable-next-line sonarjs/no-duplicated-branches } else if ((values = combinedNewFile.exec(line))) { currentFile.newFileMode = values[1]; currentFile.isNew = true; + // eslint-disable-next-line sonarjs/no-duplicated-branches } else if ((values = combinedDeletedFile.exec(line))) { currentFile.deletedFileMode = values[1]; currentFile.isDeleted = true; diff --git a/src/diff2html.ts b/src/diff2html.ts index 1275eeb..5daed0e 100644 --- a/src/diff2html.ts +++ b/src/diff2html.ts @@ -1,9 +1,9 @@ -import * as DiffParser from "./diff-parser"; -import * as fileListPrinter from "./file-list-renderer"; -import LineByLineRenderer, { LineByLineRendererConfig, defaultLineByLineRendererConfig } from "./line-by-line-renderer"; -import SideBySideRenderer, { SideBySideRendererConfig, defaultSideBySideRendererConfig } from "./side-by-side-renderer"; -import { DiffFile, OutputFormatType } from "./types"; -import HoganJsUtils, { HoganJsUtilsConfig } from "./hoganjs-utils"; +import * as DiffParser from './diff-parser'; +import * as fileListPrinter from './file-list-renderer'; +import LineByLineRenderer, { LineByLineRendererConfig, defaultLineByLineRendererConfig } from './line-by-line-renderer'; +import SideBySideRenderer, { SideBySideRendererConfig, defaultSideBySideRendererConfig } from './side-by-side-renderer'; +import { DiffFile, OutputFormatType } from './types'; +import HoganJsUtils, { HoganJsUtilsConfig } from './hoganjs-utils'; export interface Diff2HtmlConfig extends DiffParser.DiffParserConfig, @@ -18,7 +18,7 @@ export const defaultDiff2HtmlConfig = { ...defaultLineByLineRendererConfig, ...defaultSideBySideRendererConfig, outputFormat: OutputFormatType.LINE_BY_LINE, - drawFileList: true + drawFileList: true, }; export function parse(diffInput: string, configuration: Diff2HtmlConfig = {}): DiffFile[] { @@ -28,14 +28,14 @@ export function parse(diffInput: string, configuration: Diff2HtmlConfig = {}): D export function html(diffInput: string | DiffFile[], configuration: Diff2HtmlConfig = {}): string { const config = { ...defaultDiff2HtmlConfig, ...configuration }; - const diffJson = typeof diffInput === "string" ? DiffParser.parse(diffInput, config) : diffInput; + const diffJson = typeof diffInput === 'string' ? DiffParser.parse(diffInput, config) : diffInput; const hoganUtils = new HoganJsUtils(config); - const fileList = config.drawFileList ? fileListPrinter.render(diffJson, hoganUtils) : ""; + const fileList = config.drawFileList ? fileListPrinter.render(diffJson, hoganUtils) : ''; const diffOutput = - config.outputFormat === "side-by-side" + config.outputFormat === 'side-by-side' ? new SideBySideRenderer(hoganUtils, config).render(diffJson) : new LineByLineRenderer(hoganUtils, config).render(diffJson); diff --git a/src/file-list-renderer.ts b/src/file-list-renderer.ts index 8d2b2d8..90836c4 100644 --- a/src/file-list-renderer.ts +++ b/src/file-list-renderer.ts @@ -1,33 +1,33 @@ -import * as renderUtils from "./render-utils"; -import HoganJsUtils from "./hoganjs-utils"; -import { DiffFile } from "./types"; +import * as renderUtils from './render-utils'; +import HoganJsUtils from './hoganjs-utils'; +import { DiffFile } from './types'; -const baseTemplatesPath = "file-summary"; -const iconsBaseTemplatesPath = "icon"; +const baseTemplatesPath = 'file-summary'; +const iconsBaseTemplatesPath = 'icon'; export function render(diffFiles: DiffFile[], hoganUtils: HoganJsUtils): string { const files = diffFiles .map(file => hoganUtils.render( baseTemplatesPath, - "line", + 'line', { fileHtmlId: renderUtils.getHtmlId(file), oldName: file.oldName, newName: file.newName, fileName: renderUtils.filenameDiff(file), - deletedLines: "-" + file.deletedLines, - addedLines: "+" + file.addedLines + deletedLines: '-' + file.deletedLines, + addedLines: '+' + file.addedLines, }, { - fileIcon: hoganUtils.template(iconsBaseTemplatesPath, renderUtils.getFileIcon(file)) - } - ) + fileIcon: hoganUtils.template(iconsBaseTemplatesPath, renderUtils.getFileIcon(file)), + }, + ), ) - .join("\n"); + .join('\n'); - return hoganUtils.render(baseTemplatesPath, "wrapper", { + return hoganUtils.render(baseTemplatesPath, 'wrapper', { filesNumber: diffFiles.length, - files: files + files: files, }); } diff --git a/src/hoganjs-utils.ts b/src/hoganjs-utils.ts index 4ae987d..88b54e5 100644 --- a/src/hoganjs-utils.ts +++ b/src/hoganjs-utils.ts @@ -1,6 +1,6 @@ -import * as Hogan from "hogan.js"; +import * as Hogan from 'hogan.js'; -import { defaultTemplates } from "./diff2html-templates"; +import { defaultTemplates } from './diff2html-templates'; export interface RawTemplates { [name: string]: string; @@ -24,7 +24,7 @@ export default class HoganJsUtils { const compiledTemplate: Hogan.Template = Hogan.compile(templateString, { asString: false }); return { ...previousTemplates, [name]: compiledTemplate }; }, - {} + {}, ); this.preCompiledTemplates = { ...defaultTemplates, ...compiledTemplates, ...compiledRawTemplates }; diff --git a/src/line-by-line-renderer.ts b/src/line-by-line-renderer.ts index 02fd731..fd911cc 100644 --- a/src/line-by-line-renderer.ts +++ b/src/line-by-line-renderer.ts @@ -1,6 +1,6 @@ -import HoganJsUtils from "./hoganjs-utils"; -import * as Rematch from "./rematch"; -import * as renderUtils from "./render-utils"; +import HoganJsUtils from './hoganjs-utils'; +import * as Rematch from './rematch'; +import * as renderUtils from './render-utils'; import { DiffFile, DiffLine, @@ -9,8 +9,8 @@ import { DiffLineDeleted, DiffLineContent, DiffLineContext, - DiffLineInserted -} from "./types"; + DiffLineInserted, +} from './types'; export interface LineByLineRendererConfig extends renderUtils.RenderConfig { renderNothingWhenEmpty?: boolean; @@ -22,13 +22,13 @@ export const defaultLineByLineRendererConfig = { ...renderUtils.defaultRenderConfig, renderNothingWhenEmpty: false, matchingMaxComparisons: 2500, - maxLineSizeInBlockForComparison: 200 + maxLineSizeInBlockForComparison: 200, }; -const genericTemplatesPath = "generic"; -const baseTemplatesPath = "line-by-line"; -const iconsBaseTemplatesPath = "icon"; -const tagsBaseTemplatesPath = "tag"; +const genericTemplatesPath = 'generic'; +const baseTemplatesPath = 'line-by-line'; +const iconsBaseTemplatesPath = 'icon'; +const tagsBaseTemplatesPath = 'tag'; export default class LineByLineRenderer { private readonly hoganUtils: HoganJsUtils; @@ -50,17 +50,17 @@ export default class LineByLineRenderer { } return this.makeFileDiffHtml(file, diffs); }) - .join("\n"); + .join('\n'); - return this.hoganUtils.render(genericTemplatesPath, "wrapper", { content: diffsHtml }); + return this.hoganUtils.render(genericTemplatesPath, 'wrapper', { content: diffsHtml }); } makeFileDiffHtml(file: DiffFile, diffs: string): string { - if (this.config.renderNothingWhenEmpty && Array.isArray(file.blocks) && file.blocks.length === 0) return ""; + if (this.config.renderNothingWhenEmpty && Array.isArray(file.blocks) && file.blocks.length === 0) return ''; - const fileDiffTemplate = this.hoganUtils.template(baseTemplatesPath, "file-diff"); - const filePathTemplate = this.hoganUtils.template(genericTemplatesPath, "file-path"); - const fileIconTemplate = this.hoganUtils.template(iconsBaseTemplatesPath, "file"); + const fileDiffTemplate = this.hoganUtils.template(baseTemplatesPath, 'file-diff'); + const filePathTemplate = this.hoganUtils.template(genericTemplatesPath, 'file-path'); + const fileIconTemplate = this.hoganUtils.template(iconsBaseTemplatesPath, 'file'); const fileTagTemplate = this.hoganUtils.template(tagsBaseTemplatesPath, renderUtils.getFileIcon(file)); return fileDiffTemplate.render({ @@ -69,35 +69,35 @@ export default class LineByLineRenderer { diffs: diffs, filePath: filePathTemplate.render( { - fileDiffName: renderUtils.filenameDiff(file) + fileDiffName: renderUtils.filenameDiff(file), }, { fileIcon: fileIconTemplate, - fileTag: fileTagTemplate - } - ) + fileTag: fileTagTemplate, + }, + ), }); } generateEmptyDiff(): string { - return this.hoganUtils.render(genericTemplatesPath, "empty-diff", { - contentClass: "d2h-code-line", - CSSLineClass: renderUtils.CSSLineClass + return this.hoganUtils.render(genericTemplatesPath, 'empty-diff', { + contentClass: 'd2h-code-line', + CSSLineClass: renderUtils.CSSLineClass, }); } generateFileHtml(file: DiffFile): string { const matcher = Rematch.newMatcherFn( - Rematch.newDistanceFn((e: DiffLine) => renderUtils.deconstructLine(e.content, file.isCombined).content) + Rematch.newDistanceFn((e: DiffLine) => renderUtils.deconstructLine(e.content, file.isCombined).content), ); return file.blocks .map(block => { - let lines = this.hoganUtils.render(genericTemplatesPath, "block-header", { + let lines = this.hoganUtils.render(genericTemplatesPath, 'block-header', { CSSLineClass: renderUtils.CSSLineClass, blockHeader: block.header, - lineClass: "d2h-code-linenumber", - contentClass: "d2h-code-line" + lineClass: 'd2h-code-linenumber', + contentClass: 'd2h-code-line', }); this.applyLineGroupping(block).forEach(([contextLines, oldLines, newLines]) => { @@ -115,7 +115,7 @@ export default class LineByLineRenderer { prefix: prefix, content: content, oldNumber: line.oldNumber, - newNumber: line.newNumber + newNumber: line.newNumber, }); }); } else if (oldLines.length || newLines.length) { @@ -123,13 +123,13 @@ export default class LineByLineRenderer { lines += left; lines += right; } else { - console.error("Unknown state reached while processing groups of lines", contextLines, oldLines, newLines); + console.error('Unknown state reached while processing groups of lines', contextLines, oldLines, newLines); } }); return lines; }) - .join("\n"); + .join('\n'); } applyLineGroupping(block: DiffBlock): DiffLineGroups { @@ -173,27 +173,25 @@ export default class LineByLineRenderer { applyRematchMatching( oldLines: DiffLine[], newLines: DiffLine[], - matcher: Rematch.MatcherFn + matcher: Rematch.MatcherFn, ): DiffLine[][][] { const comparisons = oldLines.length * newLines.length; const maxLineSizeInBlock = Math.max.apply( null, - [0].concat(oldLines.concat(newLines).map(elem => elem.content.length)) + [0].concat(oldLines.concat(newLines).map(elem => elem.content.length)), ); const doMatching = comparisons < this.config.matchingMaxComparisons && maxLineSizeInBlock < this.config.maxLineSizeInBlockForComparison && - (this.config.matching === "lines" || this.config.matching === "words"); + (this.config.matching === 'lines' || this.config.matching === 'words'); - const matches = doMatching ? matcher(oldLines, newLines) : [[oldLines, newLines]]; - - return matches; + return doMatching ? matcher(oldLines, newLines) : [[oldLines, newLines]]; } processChangedLines(isCombined: boolean, oldLines: DiffLine[], newLines: DiffLine[]): FileHtml { const fileHtml = { - right: "", - left: "" + right: '', + left: '', }; const maxLinesNumber = Math.max(oldLines.length, newLines.length); @@ -213,14 +211,14 @@ export default class LineByLineRenderer { ? { prefix: diff.oldLine.prefix, content: diff.oldLine.content, - type: renderUtils.CSSLineClass.DELETE_CHANGES + type: renderUtils.CSSLineClass.DELETE_CHANGES, } : { ...renderUtils.deconstructLine(oldLine.content, isCombined), - type: renderUtils.toCSSClass(oldLine.type) + type: renderUtils.toCSSClass(oldLine.type), }), oldNumber: oldLine.oldNumber, - newNumber: oldLine.newNumber + newNumber: oldLine.newNumber, } : undefined; @@ -231,14 +229,14 @@ export default class LineByLineRenderer { ? { prefix: diff.newLine.prefix, content: diff.newLine.content, - type: renderUtils.CSSLineClass.INSERT_CHANGES + type: renderUtils.CSSLineClass.INSERT_CHANGES, } : { ...renderUtils.deconstructLine(newLine.content, isCombined), - type: renderUtils.toCSSClass(newLine.type) + type: renderUtils.toCSSClass(newLine.type), }), oldNumber: newLine.oldNumber, - newNumber: newLine.newNumber + newNumber: newLine.newNumber, } : undefined; @@ -253,25 +251,25 @@ export default class LineByLineRenderer { generateLineHtml(oldLine?: DiffPreparedLine, newLine?: DiffPreparedLine): FileHtml { return { left: this.generateSingleLineHtml(oldLine), - right: this.generateSingleLineHtml(newLine) + right: this.generateSingleLineHtml(newLine), }; } generateSingleLineHtml(line?: DiffPreparedLine): string { - if (line === undefined) return ""; + if (line === undefined) return ''; - const lineNumberHtml = this.hoganUtils.render(baseTemplatesPath, "numbers", { - oldNumber: line.oldNumber || "", - newNumber: line.newNumber || "" + const lineNumberHtml = this.hoganUtils.render(baseTemplatesPath, 'numbers', { + oldNumber: line.oldNumber || '', + newNumber: line.newNumber || '', }); - return this.hoganUtils.render(genericTemplatesPath, "line", { + return this.hoganUtils.render(genericTemplatesPath, 'line', { type: line.type, - lineClass: "d2h-code-linenumber", - contentClass: "d2h-code-line", - prefix: line.prefix === " " ? " " : line.prefix, + lineClass: 'd2h-code-linenumber', + contentClass: 'd2h-code-line', + prefix: line.prefix === ' ' ? ' ' : line.prefix, content: line.content, - lineNumber: lineNumberHtml + lineNumber: lineNumberHtml, }); } } @@ -279,7 +277,7 @@ export default class LineByLineRenderer { type DiffLineGroups = [ (DiffLineContext & DiffLineContent)[], (DiffLineDeleted & DiffLineContent)[], - (DiffLineInserted & DiffLineContent)[] + (DiffLineInserted & DiffLineContent)[], ][]; type DiffPreparedLine = { diff --git a/src/rematch.ts b/src/rematch.ts index 5e7ea3b..2899aa5 100644 --- a/src/rematch.ts +++ b/src/rematch.ts @@ -53,8 +53,8 @@ export function levenshtein(a: string, b: string): number { matrix[i - 1][j - 1] + 1, // Substitution Math.min( matrix[i][j - 1] + 1, // Insertion - matrix[i - 1][j] + 1 - ) + matrix[i - 1][j] + 1, + ), ); // Deletion } } @@ -70,9 +70,7 @@ export function newDistanceFn(str: (value: T) => string): DistanceFn { const xValue = str(x).trim(); const yValue = str(y).trim(); const lev = levenshtein(xValue, yValue); - const score = lev / (xValue.length + yValue.length); - - return score; + return lev / (xValue.length + yValue.length); }; } diff --git a/src/render-utils.ts b/src/render-utils.ts index 73a1c60..6cdf7b8 100644 --- a/src/render-utils.ts +++ b/src/render-utils.ts @@ -1,16 +1,16 @@ -import * as jsDiff from "diff"; +import * as jsDiff from 'diff'; -import { unifyPath, hashCode } from "./utils"; -import * as rematch from "./rematch"; -import { LineMatchingType, DiffStyleType, LineType, DiffLineParts, DiffFile, DiffFileName } from "./types"; +import { unifyPath, hashCode } from './utils'; +import * as rematch from './rematch'; +import { LineMatchingType, DiffStyleType, LineType, DiffLineParts, DiffFile, DiffFileName } from './types'; export enum CSSLineClass { - INSERTS = "d2h-ins", - DELETES = "d2h-del", - CONTEXT = "d2h-cntx", - INFO = "d2h-info", - INSERT_CHANGES = "d2h-ins d2h-change", - DELETE_CHANGES = "d2h-del d2h-change" + INSERTS = 'd2h-ins', + DELETES = 'd2h-del', + CONTEXT = 'd2h-cntx', + INFO = 'd2h-info', + INSERT_CHANGES = 'd2h-ins d2h-change', + DELETE_CHANGES = 'd2h-del d2h-change', } export type HighlightedLines = { @@ -35,23 +35,23 @@ export const defaultRenderConfig = { matching: LineMatchingType.NONE, matchWordsThreshold: 0.25, maxLineLengthHighlight: 10000, - diffStyle: DiffStyleType.WORD + diffStyle: DiffStyleType.WORD, }; -const separator = "/"; +const separator = '/'; const distance = rematch.newDistanceFn((change: jsDiff.Change) => change.value); const matcher = rematch.newMatcherFn(distance); function isDevNullName(name: string): boolean { - return name.indexOf("dev/null") !== -1; + return name.indexOf('dev/null') !== -1; } function removeInsElements(line: string): string { - return line.replace(/(]*>((.|\n)*?)<\/ins>)/g, ""); + return line.replace(/(]*>((.|\n)*?)<\/ins>)/g, ''); } function removeDelElements(line: string): string { - return line.replace(/(]*>((.|\n)*?)<\/del>)/g, ""); + return line.replace(/(]*>((.|\n)*?)<\/del>)/g, ''); } /** @@ -82,12 +82,12 @@ function prefixLength(isCombined: boolean): number { export function escapeForHtml(str: string): string { return str .slice(0) - .replace(/&/g, "&") - .replace(//g, ">") - .replace(/"/g, """) - .replace(/'/g, "'") - .replace(/\//g, "/"); + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(/\//g, '/'); } /** @@ -97,7 +97,7 @@ export function deconstructLine(line: string, isCombined: boolean): DiffLinePart const indexToSplit = prefixLength(isCombined); return { prefix: line.substring(0, indexToSplit), - content: escapeForHtml(line.substring(indexToSplit)) + content: escapeForHtml(line.substring(indexToSplit)), }; } @@ -158,15 +158,15 @@ export function filenameDiff(file: DiffFileName): string { if (finalPrefix.length && finalSuffix.length) { return ( - finalPrefix + separator + "{" + oldRemainingPath + " → " + newRemainingPath + "}" + separator + finalSuffix + finalPrefix + separator + '{' + oldRemainingPath + ' → ' + newRemainingPath + '}' + separator + finalSuffix ); } else if (finalPrefix.length) { - return finalPrefix + separator + "{" + oldRemainingPath + " → " + newRemainingPath + "}"; + return finalPrefix + separator + '{' + oldRemainingPath + ' → ' + newRemainingPath + '}'; } else if (finalSuffix.length) { - return "{" + oldRemainingPath + " → " + newRemainingPath + "}" + separator + finalSuffix; + return '{' + oldRemainingPath + ' → ' + newRemainingPath + '}' + separator + finalSuffix; } - return oldFilename + " → " + newFilename; + return oldFilename + ' → ' + newFilename; } else if (!isDevNullName(newFilename)) { return newFilename; } else { @@ -187,19 +187,19 @@ export function getHtmlId(file: DiffFileName): string { * Selects the correct icon name for the file */ export function getFileIcon(file: DiffFile): string { - let templateName = "file-changed"; + let templateName = 'file-changed'; if (file.isRename) { - templateName = "file-renamed"; + templateName = 'file-renamed'; } else if (file.isCopy) { - templateName = "file-renamed"; + templateName = 'file-renamed'; } else if (file.isNew) { - templateName = "file-added"; + templateName = 'file-added'; } else if (file.isDeleted) { - templateName = "file-deleted"; + templateName = 'file-deleted'; } else if (file.newName !== file.oldName) { // If file is not Added, not Deleted and the names changed it must be a rename :) - templateName = "file-renamed"; + templateName = 'file-renamed'; } return templateName; @@ -212,7 +212,7 @@ export function diffHighlight( diffLine1: string, diffLine2: string, isCombined: boolean, - config: RenderConfig = {} + config: RenderConfig = {}, ): HighlightedLines { const { matching, maxLineLengthHighlight, matchWordsThreshold, diffStyle } = { ...defaultRenderConfig, ...config }; @@ -223,22 +223,22 @@ export function diffHighlight( return { oldLine: { prefix: line1.prefix, - content: line1.content + content: line1.content, }, newLine: { prefix: line2.prefix, - content: line2.content - } + content: line2.content, + }, }; } const diff = - diffStyle === "char" + diffStyle === 'char' ? jsDiff.diffChars(line1.content, line2.content) : jsDiff.diffWordsWithSpace(line1.content, line2.content); const changedWords: jsDiff.Change[] = []; - if (diffStyle === "word" && matching === "words") { + if (diffStyle === 'word' && matching === 'words') { const removed = diff.filter(element => element.removed); const added = diff.filter(element => element.added); const chunks = matcher(added, removed); @@ -254,22 +254,22 @@ export function diffHighlight( } const highlightedLine = diff.reduce((highlightedLine, part) => { - const elemType = part.added ? "ins" : part.removed ? "del" : null; - const addClass = changedWords.indexOf(part) > -1 ? ' class="d2h-change"' : ""; + const elemType = part.added ? 'ins' : part.removed ? 'del' : null; + const addClass = changedWords.indexOf(part) > -1 ? ' class="d2h-change"' : ''; return elemType !== null ? `${highlightedLine}<${elemType}${addClass}>${part.value}` : `${highlightedLine}${part.value}`; - }, ""); + }, ''); return { oldLine: { prefix: line1.prefix, - content: removeInsElements(highlightedLine) + content: removeInsElements(highlightedLine), }, newLine: { prefix: line2.prefix, - content: removeDelElements(highlightedLine) - } + content: removeDelElements(highlightedLine), + }, }; } diff --git a/src/side-by-side-renderer.ts b/src/side-by-side-renderer.ts index 72daa14..08209bf 100644 --- a/src/side-by-side-renderer.ts +++ b/src/side-by-side-renderer.ts @@ -1,6 +1,6 @@ -import HoganJsUtils from "./hoganjs-utils"; -import * as Rematch from "./rematch"; -import * as renderUtils from "./render-utils"; +import HoganJsUtils from './hoganjs-utils'; +import * as Rematch from './rematch'; +import * as renderUtils from './render-utils'; import { DiffLine, LineType, @@ -9,8 +9,8 @@ import { DiffLineContext, DiffLineDeleted, DiffLineInserted, - DiffLineContent -} from "./types"; + DiffLineContent, +} from './types'; export interface SideBySideRendererConfig extends renderUtils.RenderConfig { renderNothingWhenEmpty?: boolean; @@ -22,13 +22,13 @@ export const defaultSideBySideRendererConfig = { ...renderUtils.defaultRenderConfig, renderNothingWhenEmpty: false, matchingMaxComparisons: 2500, - maxLineSizeInBlockForComparison: 200 + maxLineSizeInBlockForComparison: 200, }; -const genericTemplatesPath = "generic"; -const baseTemplatesPath = "side-by-side"; -const iconsBaseTemplatesPath = "icon"; -const tagsBaseTemplatesPath = "tag"; +const genericTemplatesPath = 'generic'; +const baseTemplatesPath = 'side-by-side'; +const iconsBaseTemplatesPath = 'icon'; +const tagsBaseTemplatesPath = 'tag'; export default class SideBySideRenderer { private readonly hoganUtils: HoganJsUtils; @@ -50,17 +50,17 @@ export default class SideBySideRenderer { } return this.makeFileDiffHtml(file, diffs); }) - .join("\n"); + .join('\n'); - return this.hoganUtils.render(genericTemplatesPath, "wrapper", { content: diffsHtml }); + return this.hoganUtils.render(genericTemplatesPath, 'wrapper', { content: diffsHtml }); } makeFileDiffHtml(file: DiffFile, diffs: FileHtml): string { - if (this.config.renderNothingWhenEmpty && Array.isArray(file.blocks) && file.blocks.length === 0) return ""; + if (this.config.renderNothingWhenEmpty && Array.isArray(file.blocks) && file.blocks.length === 0) return ''; - const fileDiffTemplate = this.hoganUtils.template(baseTemplatesPath, "file-diff"); - const filePathTemplate = this.hoganUtils.template(genericTemplatesPath, "file-path"); - const fileIconTemplate = this.hoganUtils.template(iconsBaseTemplatesPath, "file"); + const fileDiffTemplate = this.hoganUtils.template(baseTemplatesPath, 'file-diff'); + const filePathTemplate = this.hoganUtils.template(genericTemplatesPath, 'file-path'); + const fileIconTemplate = this.hoganUtils.template(iconsBaseTemplatesPath, 'file'); const fileTagTemplate = this.hoganUtils.template(tagsBaseTemplatesPath, renderUtils.getFileIcon(file)); return fileDiffTemplate.render({ @@ -69,36 +69,36 @@ export default class SideBySideRenderer { diffs: diffs, filePath: filePathTemplate.render( { - fileDiffName: renderUtils.filenameDiff(file) + fileDiffName: renderUtils.filenameDiff(file), }, { fileIcon: fileIconTemplate, - fileTag: fileTagTemplate - } - ) + fileTag: fileTagTemplate, + }, + ), }); } generateEmptyDiff(): FileHtml { return { - right: "", - left: this.hoganUtils.render(genericTemplatesPath, "empty-diff", { - contentClass: "d2h-code-side-line", - CSSLineClass: renderUtils.CSSLineClass - }) + right: '', + left: this.hoganUtils.render(genericTemplatesPath, 'empty-diff', { + contentClass: 'd2h-code-side-line', + CSSLineClass: renderUtils.CSSLineClass, + }), }; } generateFileHtml(file: DiffFile): FileHtml { const matcher = Rematch.newMatcherFn( - Rematch.newDistanceFn((e: DiffLine) => renderUtils.deconstructLine(e.content, file.isCombined).content) + Rematch.newDistanceFn((e: DiffLine) => renderUtils.deconstructLine(e.content, file.isCombined).content), ); return file.blocks .map(block => { const fileHtml = { left: this.makeHeaderHtml(block.header), - right: this.makeHeaderHtml("") + right: this.makeHeaderHtml(''), }; this.applyLineGroupping(block).forEach(([contextLines, oldLines, newLines]) => { @@ -116,14 +116,14 @@ export default class SideBySideRenderer { type: renderUtils.CSSLineClass.CONTEXT, prefix: prefix, content: content, - number: line.oldNumber + number: line.oldNumber, }, { type: renderUtils.CSSLineClass.CONTEXT, prefix: prefix, content: content, - number: line.newNumber - } + number: line.newNumber, + }, ); fileHtml.left += left; fileHtml.right += right; @@ -133,7 +133,7 @@ export default class SideBySideRenderer { fileHtml.left += left; fileHtml.right += right; } else { - console.error("Unknown state reached while processing groups of lines", contextLines, oldLines, newLines); + console.error('Unknown state reached while processing groups of lines', contextLines, oldLines, newLines); } }); @@ -143,7 +143,7 @@ export default class SideBySideRenderer { (accomulated, html) => { return { left: accomulated.left + html.left, right: accomulated.right + html.right }; }, - { left: "", right: "" } + { left: '', right: '' }, ); } @@ -188,36 +188,34 @@ export default class SideBySideRenderer { applyRematchMatching( oldLines: DiffLine[], newLines: DiffLine[], - matcher: Rematch.MatcherFn + matcher: Rematch.MatcherFn, ): DiffLine[][][] { const comparisons = oldLines.length * newLines.length; const maxLineSizeInBlock = Math.max.apply( null, - [0].concat(oldLines.concat(newLines).map(elem => elem.content.length)) + [0].concat(oldLines.concat(newLines).map(elem => elem.content.length)), ); const doMatching = comparisons < this.config.matchingMaxComparisons && maxLineSizeInBlock < this.config.maxLineSizeInBlockForComparison && - (this.config.matching === "lines" || this.config.matching === "words"); + (this.config.matching === 'lines' || this.config.matching === 'words'); - const matches = doMatching ? matcher(oldLines, newLines) : [[oldLines, newLines]]; - - return matches; + return doMatching ? matcher(oldLines, newLines) : [[oldLines, newLines]]; } makeHeaderHtml(blockHeader: string): string { - return this.hoganUtils.render(genericTemplatesPath, "block-header", { + return this.hoganUtils.render(genericTemplatesPath, 'block-header', { CSSLineClass: renderUtils.CSSLineClass, blockHeader: blockHeader, - lineClass: "d2h-code-side-linenumber", - contentClass: "d2h-code-side-line" + lineClass: 'd2h-code-side-linenumber', + contentClass: 'd2h-code-side-line', }); } processChangedLines(isCombined: boolean, oldLines: DiffLine[], newLines: DiffLine[]): FileHtml { const fileHtml = { - right: "", - left: "" + right: '', + left: '', }; const maxLinesNumber = Math.max(oldLines.length, newLines.length); @@ -237,13 +235,13 @@ export default class SideBySideRenderer { ? { prefix: diff.oldLine.prefix, content: diff.oldLine.content, - type: renderUtils.CSSLineClass.DELETE_CHANGES + type: renderUtils.CSSLineClass.DELETE_CHANGES, } : { ...renderUtils.deconstructLine(oldLine.content, isCombined), - type: renderUtils.toCSSClass(oldLine.type) + type: renderUtils.toCSSClass(oldLine.type), }), - number: oldLine.oldNumber + number: oldLine.oldNumber, } : undefined; @@ -254,13 +252,13 @@ export default class SideBySideRenderer { ? { prefix: diff.newLine.prefix, content: diff.newLine.content, - type: renderUtils.CSSLineClass.INSERT_CHANGES + type: renderUtils.CSSLineClass.INSERT_CHANGES, } : { ...renderUtils.deconstructLine(newLine.content, isCombined), - type: renderUtils.toCSSClass(newLine.type) + type: renderUtils.toCSSClass(newLine.type), }), - number: newLine.newNumber + number: newLine.newNumber, } : undefined; @@ -275,21 +273,21 @@ export default class SideBySideRenderer { generateLineHtml(oldLine?: DiffPreparedLine, newLine?: DiffPreparedLine): FileHtml { return { left: this.generateSingleHtml(oldLine), - right: this.generateSingleHtml(newLine) + right: this.generateSingleHtml(newLine), }; } generateSingleHtml(line?: DiffPreparedLine): string { - const lineClass = "d2h-code-side-linenumber"; - const contentClass = "d2h-code-side-line"; + const lineClass = 'd2h-code-side-linenumber'; + const contentClass = 'd2h-code-side-line'; - return this.hoganUtils.render(genericTemplatesPath, "line", { + return this.hoganUtils.render(genericTemplatesPath, 'line', { type: line?.type || `${renderUtils.CSSLineClass.CONTEXT} d2h-emptyplaceholder`, lineClass: line !== undefined ? lineClass : `${lineClass} d2h-code-side-emptyplaceholder`, contentClass: line !== undefined ? contentClass : `${contentClass} d2h-code-side-emptyplaceholder`, - prefix: line?.prefix === " " ? " " : line?.prefix || " ", - content: line?.content || " ", - lineNumber: line?.number + prefix: line?.prefix === ' ' ? ' ' : line?.prefix || ' ', + content: line?.content || ' ', + lineNumber: line?.number, }); } } @@ -297,7 +295,7 @@ export default class SideBySideRenderer { type DiffLineGroups = [ (DiffLineContext & DiffLineContent)[], (DiffLineDeleted & DiffLineContent)[], - (DiffLineInserted & DiffLineContent)[] + (DiffLineInserted & DiffLineContent)[], ][]; type DiffPreparedLine = { diff --git a/src/types.ts b/src/types.ts index f080f16..a7515f7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -4,9 +4,9 @@ export type DiffLineParts = { }; export enum LineType { - INSERT = "insert", - DELETE = "delete", - CONTEXT = "context" + INSERT = 'insert', + DELETE = 'delete', + CONTEXT = 'context', } export interface DiffLineDeleted { @@ -70,17 +70,17 @@ export interface DiffFile extends DiffFileName { } export enum OutputFormatType { - LINE_BY_LINE = "line-by-line", - SIDE_BY_SIDE = "side-by-side" + LINE_BY_LINE = 'line-by-line', + SIDE_BY_SIDE = 'side-by-side', } export enum LineMatchingType { - LINES = "lines", - WORDS = "words", - NONE = "none" + LINES = 'lines', + WORDS = 'words', + NONE = 'none', } export enum DiffStyleType { - WORD = "word", - CHAR = "char" + WORD = 'word', + CHAR = 'char', } diff --git a/src/ui/css/diff2html.css b/src/ui/css/diff2html.css index eb0828e..bdfd56f 100644 --- a/src/ui/css/diff2html.css +++ b/src/ui/css/diff2html.css @@ -51,7 +51,7 @@ -ms-flex-align: center; align-items: center; width: 100%; - font-family: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 15px; } @@ -70,7 +70,7 @@ .d2h-diff-table { width: 100%; border-collapse: collapse; - font-family: "Menlo", "Consolas", monospace; + font-family: 'Menlo', 'Consolas', monospace; font-size: 13px; } diff --git a/src/ui/js/diff2html-ui-base.ts b/src/ui/js/diff2html-ui-base.ts new file mode 100644 index 0000000..0c7d116 --- /dev/null +++ b/src/ui/js/diff2html-ui-base.ts @@ -0,0 +1,228 @@ +import { HighlightJS, ICompiledMode, IHighlightResult, IAutoHighlightResult } from './highlight.js-interface'; +import { nodeStream, mergeStreams } from './highlight.js-helpers'; + +import { html, Diff2HtmlConfig, defaultDiff2HtmlConfig } from '../../diff2html'; +import { DiffFile } from '../../types'; + +export interface Diff2HtmlUIConfig extends Diff2HtmlConfig { + synchronisedScroll?: boolean; + highlight?: boolean; + fileListToggle?: boolean; + fileListStartVisible?: boolean; + smartSelection?: boolean; +} + +export const defaultDiff2HtmlUIConfig = { + ...defaultDiff2HtmlConfig, + synchronisedScroll: true, + highlight: true, + fileListToggle: true, + fileListStartVisible: false, + smartSelection: true, +}; + +export class Diff2HtmlUI { + readonly config: typeof defaultDiff2HtmlUIConfig; + readonly diffHtml: string; + readonly targetElement: HTMLElement; + readonly hljs: HighlightJS | null = null; + + currentSelectionColumnId = -1; + + constructor(diffInput: string | DiffFile[], target: HTMLElement, config: Diff2HtmlUIConfig = {}, hljs?: HighlightJS) { + this.config = { ...defaultDiff2HtmlUIConfig, ...config }; + this.diffHtml = html(diffInput, this.config); + this.targetElement = target; + if (hljs !== undefined) this.hljs = hljs; + } + + draw(): void { + this.targetElement.innerHTML = this.diffHtml; + if (this.config.smartSelection) this.initSelection(); + if (this.config.synchronisedScroll) this.synchronisedScroll(); + if (this.config.highlight) this.highlightCode(); + if (this.config.fileListToggle) this.fileListToggle(this.config.fileListStartVisible); + } + + synchronisedScroll(): void { + this.targetElement.querySelectorAll('.d2h-file-wrapper').forEach(wrapper => { + const [left, right] = [].slice.call(wrapper.querySelectorAll('.d2h-file-side-diff')) as HTMLElement[]; + if (left === undefined || right === undefined) return; + const onScroll = (event: Event): void => { + if (event === null || event.target === null) return; + if (event.target === left) { + right.scrollTop = left.scrollTop; + right.scrollLeft = left.scrollLeft; + } else { + left.scrollTop = right.scrollTop; + left.scrollLeft = right.scrollLeft; + } + }; + left.addEventListener('scroll', onScroll); + right.addEventListener('scroll', onScroll); + }); + } + + fileListToggle(startVisible: boolean): void { + const hashTag = this.getHashTag(); + + const showBtn = this.targetElement.querySelector('.d2h-show') as HTMLElement; + const hideBtn = this.targetElement.querySelector('.d2h-hide') as HTMLElement; + const fileList = this.targetElement.querySelector('.d2h-file-list') as HTMLElement; + + if (showBtn === null || hideBtn === null || fileList === null) return; + + function show(): void { + showBtn.style.display = 'none'; + hideBtn.style.display = 'inline'; + fileList.style.display = 'block'; + } + + function hide(): void { + showBtn.style.display = 'inline'; + hideBtn.style.display = 'none'; + fileList.style.display = 'none'; + } + + showBtn.addEventListener('click', () => show()); + hideBtn.addEventListener('click', () => hide()); + + if (hashTag === 'files-summary-show') show(); + else if (hashTag === 'files-summary-hide') hide(); + else if (startVisible) show(); + else hide(); + } + + highlightCode(): void { + if (this.hljs === null) { + throw new Error('Missing a `highlight.js` implementation. Please provide one when instantiating Diff2HtmlUI.'); + } + + // Collect all the diff files and execute the highlight on their lines + const files = this.targetElement.querySelectorAll('.d2h-file-wrapper'); + files.forEach(file => { + let oldLinesState: ICompiledMode; + let newLinesState: ICompiledMode; + + // Collect all the code lines and execute the highlight on them + const codeLines = file.querySelectorAll('.d2h-code-line-ctn'); + codeLines.forEach(line => { + // HACK: help Typescript know that `this.hljs` is defined since we already checked it + if (this.hljs === null) return; + + const text = line.textContent; + const lineParent = line.parentNode as HTMLElement; + + if (lineParent === null || text === null) return; + + const lineState = lineParent.className.indexOf('d2h-del') !== -1 ? oldLinesState : newLinesState; + + const language = file.getAttribute('data-lang'); + const result = + language && this.hljs.getLanguage(language) + ? this.hljs.highlight(language, text, true, lineState) + : this.hljs.highlightAuto(text); + + if (this.instanceOfIHighlightResult(result)) { + if (lineParent.className.indexOf('d2h-del') !== -1) { + oldLinesState = result.top; + } else if (lineParent.className.indexOf('d2h-ins') !== -1) { + newLinesState = result.top; + } else { + oldLinesState = result.top; + newLinesState = result.top; + } + } + + const originalStream = nodeStream(line); + if (originalStream.length) { + const resultNode = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); + resultNode.innerHTML = result.value; + result.value = mergeStreams(originalStream, nodeStream(resultNode), text); + } + + line.classList.add('hljs'); + line.classList.add('result.language'); + line.innerHTML = result.value; + }); + }); + } + + private instanceOfIHighlightResult(object: IHighlightResult | IAutoHighlightResult): object is IHighlightResult { + return 'top' in object; + } + + private getHashTag(): string | null { + const docUrl = document.URL; + const hashTagIndex = docUrl.indexOf('#'); + + let hashTag = null; + if (hashTagIndex !== -1) { + hashTag = docUrl.substr(hashTagIndex + 1); + } + + return hashTag; + } + + private initSelection(): void { + const body = document.getElementsByTagName('body')[0]; + const diffTable = body.getElementsByClassName('d2h-diff-table')[0]; + + diffTable.addEventListener('mousedown', event => { + if (event === null || event.target === null) return; + + const mouseEvent = event as MouseEvent; + const target = mouseEvent.target as HTMLElement; + const table = target.closest('.d2h-diff-table'); + + if (table !== null) { + if (target.closest('.d2h-code-line,.d2h-code-side-line') !== null) { + table.classList.remove('selecting-left'); + table.classList.add('selecting-right'); + this.currentSelectionColumnId = 1; + } else if (target.closest('.d2h-code-linenumber,.d2h-code-side-linenumber') !== null) { + table.classList.remove('selecting-right'); + table.classList.add('selecting-left'); + this.currentSelectionColumnId = 0; + } + } + }); + + diffTable.addEventListener('copy', event => { + const clipboardEvent = event as ClipboardEvent; + const clipboardData = clipboardEvent.clipboardData; + const text = this.getSelectedText(); + + if (clipboardData === null || text === undefined) return; + + clipboardData.setData('text', text); + event.preventDefault(); + }); + } + + private getSelectedText(): string | undefined { + const sel = window.getSelection(); + + if (sel === null) return; + + const range = sel.getRangeAt(0); + const doc = range.cloneContents(); + const nodes = doc.querySelectorAll('tr'); + const idx = this.currentSelectionColumnId; + + let text = ''; + if (nodes.length === 0) { + text = doc.textContent || ''; + } else { + nodes.forEach((tr, i) => { + const td = tr.cells[tr.cells.length === 1 ? 0 : idx]; + + if (td === undefined || td.textContent === null) return; + + text += (i ? '\n' : '') + td.textContent.replace(/\r\n|\r|\n/g, ''); + }); + } + + return text; + } +} diff --git a/src/ui/js/diff2html-ui-slim.ts b/src/ui/js/diff2html-ui-slim.ts new file mode 100644 index 0000000..86d40af --- /dev/null +++ b/src/ui/js/diff2html-ui-slim.ts @@ -0,0 +1,12 @@ +import { hljs } from './highlight.js-slim'; + +import { DiffFile } from '../../types'; +import { Diff2HtmlUI as Diff2HtmlUIBase, Diff2HtmlUIConfig, defaultDiff2HtmlUIConfig } from './diff2html-ui-base'; + +export class Diff2HtmlUI extends Diff2HtmlUIBase { + constructor(diffInput: string | DiffFile[], target: HTMLElement, config: Diff2HtmlUIConfig = {}) { + super(diffInput, target, config, hljs); + } +} + +export { Diff2HtmlUIConfig, defaultDiff2HtmlUIConfig }; diff --git a/src/ui/js/diff2html-ui.ts b/src/ui/js/diff2html-ui.ts index d64bc87..eaefad2 100644 --- a/src/ui/js/diff2html-ui.ts +++ b/src/ui/js/diff2html-ui.ts @@ -1,223 +1,12 @@ -import HighlightJS from "highlight.js"; -import * as HighlightJSInternals from "./highlight.js-internals"; -import { html, Diff2HtmlConfig, defaultDiff2HtmlConfig } from "../../diff2html"; -import { DiffFile } from "../../types"; +import hljs from 'highlight.js'; -export interface Diff2HtmlUIConfig extends Diff2HtmlConfig { - synchronisedScroll?: boolean; - highlight?: boolean; - fileListToggle?: boolean; - fileListStartVisible?: boolean; - smartSelection?: boolean; -} - -export const defaultDiff2HtmlUIConfig = { - ...defaultDiff2HtmlConfig, - synchronisedScroll: true, - highlight: true, - fileListToggle: true, - fileListStartVisible: false, - smartSelection: true -}; - -export class Diff2HtmlUI { - readonly config: typeof defaultDiff2HtmlUIConfig; - readonly diffHtml: string; - targetElement: HTMLElement; - currentSelectionColumnId = -1; +import { DiffFile } from '../../types'; +import { Diff2HtmlUI as Diff2HtmlUIBase, Diff2HtmlUIConfig, defaultDiff2HtmlUIConfig } from './diff2html-ui-base'; +export class Diff2HtmlUI extends Diff2HtmlUIBase { constructor(diffInput: string | DiffFile[], target: HTMLElement, config: Diff2HtmlUIConfig = {}) { - this.config = { ...defaultDiff2HtmlUIConfig, ...config }; - this.diffHtml = html(diffInput, this.config); - this.targetElement = target; - } - - draw(): void { - this.targetElement.innerHTML = this.diffHtml; - if (this.config.smartSelection) this.initSelection(); - if (this.config.synchronisedScroll) this.synchronisedScroll(); - if (this.config.highlight) this.highlightCode(); - if (this.config.fileListToggle) this.fileListToggle(this.config.fileListStartVisible); - } - - synchronisedScroll(): void { - this.targetElement.querySelectorAll(".d2h-file-wrapper").forEach(wrapper => { - const [left, right] = [].slice.call(wrapper.querySelectorAll(".d2h-file-side-diff")) as HTMLElement[]; - if (left === undefined || right === undefined) return; - const onScroll = (event: Event): void => { - if (event === null || event.target === null) return; - if (event.target === left) { - right.scrollTop = left.scrollTop; - right.scrollLeft = left.scrollLeft; - } else { - left.scrollTop = right.scrollTop; - left.scrollLeft = right.scrollLeft; - } - }; - left.addEventListener("scroll", onScroll); - right.addEventListener("scroll", onScroll); - }); - } - - fileListToggle(startVisible: boolean): void { - const hashTag = this.getHashTag(); - - const showBtn = this.targetElement.querySelector(".d2h-show") as HTMLElement; - const hideBtn = this.targetElement.querySelector(".d2h-hide") as HTMLElement; - const fileList = this.targetElement.querySelector(".d2h-file-list") as HTMLElement; - - if (showBtn === null || hideBtn === null || fileList === null) return; - - function show(): void { - showBtn.style.display = "none"; - hideBtn.style.display = "inline"; - fileList.style.display = "block"; - } - - function hide(): void { - showBtn.style.display = "inline"; - hideBtn.style.display = "none"; - fileList.style.display = "none"; - } - - showBtn.addEventListener("click", () => show()); - hideBtn.addEventListener("click", () => hide()); - - if (hashTag === "files-summary-show") show(); - else if (hashTag === "files-summary-hide") hide(); - else if (startVisible) show(); - else hide(); - } - - highlightCode(): void { - // Collect all the diff files and execute the highlight on their lines - const files = this.targetElement.querySelectorAll(".d2h-file-wrapper"); - files.forEach(file => { - let oldLinesState: HighlightJS.ICompiledMode; - let newLinesState: HighlightJS.ICompiledMode; - - // Collect all the code lines and execute the highlight on them - const codeLines = file.querySelectorAll(".d2h-code-line-ctn"); - codeLines.forEach(line => { - const text = line.textContent; - const lineParent = line.parentNode as HTMLElement; - - if (lineParent === null || text === null) return; - - const lineState = lineParent.className.indexOf("d2h-del") !== -1 ? oldLinesState : newLinesState; - - const language = file.getAttribute("data-lang"); - const result = - language && HighlightJS.getLanguage(language) - ? HighlightJS.highlight(language, text, true, lineState) - : HighlightJS.highlightAuto(text); - - if (this.instanceOfIHighlightResult(result)) { - if (lineParent.className.indexOf("d2h-del") !== -1) { - oldLinesState = result.top; - } else if (lineParent.className.indexOf("d2h-ins") !== -1) { - newLinesState = result.top; - } else { - oldLinesState = result.top; - newLinesState = result.top; - } - } - - const originalStream = HighlightJSInternals.nodeStream(line); - if (originalStream.length) { - const resultNode = document.createElementNS("http://www.w3.org/1999/xhtml", "div"); - resultNode.innerHTML = result.value; - result.value = HighlightJSInternals.mergeStreams( - originalStream, - HighlightJSInternals.nodeStream(resultNode), - text - ); - } - - line.classList.add("hljs"); - line.classList.add("result.language"); - line.innerHTML = result.value; - }); - }); - } - - private instanceOfIHighlightResult( - object: HighlightJS.IHighlightResult | HighlightJS.IAutoHighlightResult - ): object is HighlightJS.IHighlightResult { - return "top" in object; - } - - private getHashTag(): string | null { - const docUrl = document.URL; - const hashTagIndex = docUrl.indexOf("#"); - - let hashTag = null; - if (hashTagIndex !== -1) { - hashTag = docUrl.substr(hashTagIndex + 1); - } - - return hashTag; - } - - private initSelection(): void { - const body = document.getElementsByTagName("body")[0]; - const diffTable = body.getElementsByClassName("d2h-diff-table")[0]; - - diffTable.addEventListener("mousedown", event => { - if (event === null || event.target === null) return; - - const mouseEvent = event as MouseEvent; - const target = mouseEvent.target as HTMLElement; - const table = target.closest(".d2h-diff-table"); - - if (table !== null) { - if (target.closest(".d2h-code-line,.d2h-code-side-line") !== null) { - table.classList.remove("selecting-left"); - table.classList.add("selecting-right"); - this.currentSelectionColumnId = 1; - } else if (target.closest(".d2h-code-linenumber,.d2h-code-side-linenumber") !== null) { - table.classList.remove("selecting-right"); - table.classList.add("selecting-left"); - this.currentSelectionColumnId = 0; - } - } - }); - - diffTable.addEventListener("copy", event => { - const clipboardEvent = event as ClipboardEvent; - const clipboardData = clipboardEvent.clipboardData; - const text = this.getSelectedText(); - - if (clipboardData === null || text === undefined) return; - - clipboardData.setData("text", text); - event.preventDefault(); - }); - } - - private getSelectedText(): string | undefined { - const sel = window.getSelection(); - - if (sel === null) return; - - const range = sel.getRangeAt(0); - const doc = range.cloneContents(); - const nodes = doc.querySelectorAll("tr"); - const idx = this.currentSelectionColumnId; - - let text = ""; - if (nodes.length === 0) { - text = doc.textContent || ""; - } else { - nodes.forEach((tr, i) => { - const td = tr.cells[tr.cells.length === 1 ? 0 : idx]; - - if (td === undefined || td.textContent === null) return; - - text += (i ? "\n" : "") + td.textContent.replace(/(?:\r\n|\r|\n)/g, ""); - }); - } - - return text; + super(diffInput, target, config, hljs); } } + +export { Diff2HtmlUIConfig, defaultDiff2HtmlUIConfig }; diff --git a/src/ui/js/highlight.js-internals.ts b/src/ui/js/highlight.js-helpers.ts similarity index 85% rename from src/ui/js/highlight.js-internals.ts rename to src/ui/js/highlight.js-helpers.ts index 740d75d..24e9a38 100644 --- a/src/ui/js/highlight.js-internals.ts +++ b/src/ui/js/highlight.js-helpers.ts @@ -1,15 +1,15 @@ /* - * Copied from Highlight.js Private API - * Will be removed when this part of the API is exposed + * Adapted Highlight.js Internal APIs + * Used to highlight selected html elements using context */ /* Utility functions */ function escape(value: string): string { return value - .replace(/&/gm, "&") - .replace(//gm, ">"); + .replace(/&/gm, '&') + .replace(//gm, '>'); } function tag(node: Node): string { @@ -19,7 +19,7 @@ function tag(node: Node): string { /* Stream merging */ type NodeEvent = { - event: "start" | "stop"; + event: 'start' | 'stop'; offset: number; node: Node; }; @@ -33,9 +33,9 @@ export function nodeStream(node: Node): NodeEvent[] { offset += child.nodeValue.length; } else if (child.nodeType === 1) { result.push({ - event: "start", + event: 'start', offset: offset, - node: child + node: child, }); offset = nodeStream(child, offset); // Prevent void elements from having an end tag that would actually @@ -43,9 +43,9 @@ export function nodeStream(node: Node): NodeEvent[] { // but we list only those realistically expected in code display. if (!tag(child).match(/br|hr|img|input/)) { result.push({ - event: "stop", + event: 'stop', offset: offset, - node: child + node: child, }); } } @@ -60,7 +60,7 @@ export function nodeStream(node: Node): NodeEvent[] { export function mergeStreams(original: NodeEvent[], highlighted: NodeEvent[], value: string): string { let processed = 0; - let result = ""; + let result = ''; const nodeStack = []; function selectStream(): NodeEvent[] { @@ -84,22 +84,22 @@ export function mergeStreams(original: NodeEvent[], highlighted: NodeEvent[], va return highlighted; ... which is collapsed to: */ - return highlighted[0].event === "start" ? original : highlighted; + return highlighted[0].event === 'start' ? original : highlighted; } function open(node: Node): void { const htmlNode = node as HTMLElement; result += `<${tag(node)} ${[].map .call(htmlNode.attributes, (attr: Attr) => `${attr.nodeName}="${escape(attr.value)}"`) - .join(" ")}>`; + .join(' ')}>`; } function close(node: Node): void { - result += ""; + result += ''; } function render(event: NodeEvent): void { - (event.event === "start" ? open : close)(event.node); + (event.event === 'start' ? open : close)(event.node); } while (original.length || highlighted.length) { @@ -120,7 +120,7 @@ export function mergeStreams(original: NodeEvent[], highlighted: NodeEvent[], va } while (stream === original && stream.length && stream[0].offset === processed); nodeStack.reverse().forEach(open); } else { - if (stream[0].event === "start") { + if (stream[0].event === 'start') { nodeStack.push(stream[0].node); } else { nodeStack.pop(); @@ -130,5 +130,3 @@ export function mergeStreams(original: NodeEvent[], highlighted: NodeEvent[], va } return result + escape(value.substr(processed)); } - -/* **** Highlight.js Private API **** */ diff --git a/src/ui/js/highlight.js-interface.ts b/src/ui/js/highlight.js-interface.ts new file mode 100644 index 0000000..3657dad --- /dev/null +++ b/src/ui/js/highlight.js-interface.ts @@ -0,0 +1,69 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable @typescript-eslint/interface-name-prefix */ +/* eslint-disable @typescript-eslint/camelcase */ + +export interface HighlightJS { + highlight(name: string, value: string, ignore_illegals?: boolean, continuation?: ICompiledMode): IHighlightResult; + + highlightAuto(value: string, languageSubset?: string[]): IAutoHighlightResult; + + getLanguage(name: string): IMode; +} + +export interface IAutoHighlightResult extends IHighlightResultBase { + second_best?: IAutoHighlightResult; +} + +export interface IHighlightResultBase { + relevance: number; + language: string; + value: string; +} + +export interface IHighlightResult extends IHighlightResultBase { + top: ICompiledMode; +} + +export interface IMode extends IModeBase { + keywords?: any; + contains?: IMode[]; +} + +// Reference: +// https://github.com/isagalaev/highlight.js/blob/master/docs/reference.rst +export interface IModeBase { + className?: string; + aliases?: string[]; + begin?: string | RegExp; + end?: string | RegExp; + case_insensitive?: boolean; + beginKeyword?: string; + endsWithParent?: boolean; + lexems?: string; + illegal?: string; + excludeBegin?: boolean; + excludeEnd?: boolean; + returnBegin?: boolean; + returnEnd?: boolean; + starts?: string; + subLanguage?: string; + subLanguageMode?: string; + relevance?: number; + variants?: IMode[]; +} + +export interface ICompiledMode extends IModeBase { + compiled: boolean; + contains?: ICompiledMode[]; + keywords?: Object; + terminators: RegExp; + terminator_end?: string; +} + +export interface IOptions { + classPrefix?: string; + tabReplace?: string; + useBR?: boolean; + languages?: string[]; +} diff --git a/src/ui/js/highlight.js-slim.ts b/src/ui/js/highlight.js-slim.ts new file mode 100644 index 0000000..2a26e4d --- /dev/null +++ b/src/ui/js/highlight.js-slim.ts @@ -0,0 +1,203 @@ +import { HighlightJS } from './highlight.js-interface'; + +/* eslint-disable @typescript-eslint/camelcase */ +/* eslint-disable @typescript-eslint/no-var-requires */ +/* eslint-disable @typescript-eslint/interface-name-prefix */ +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +/* + * Adapted Highlight.js External APIs + * Used to avoid importing all the languages + */ + +// Require the highlight.js library without languages +const highlightJS = require('highlight.js/lib/highlight.js'); +// Separately require languages +// highlightJS.registerLanguage('1c', require('highlight.js/lib/languages/1c')); +// highlightJS.registerLanguage('abnf', require('highlight.js/lib/languages/abnf')); +// highlightJS.registerLanguage('accesslog', require('highlight.js/lib/languages/accesslog')); +// highlightJS.registerLanguage('actionscript', require('highlight.js/lib/languages/actionscript')); +// highlightJS.registerLanguage('ada', require('highlight.js/lib/languages/ada')); +// highlightJS.registerLanguage('angelscript', require('highlight.js/lib/languages/angelscript')); +// highlightJS.registerLanguage('apache', require('highlight.js/lib/languages/apache')); +// highlightJS.registerLanguage('applescript', require('highlight.js/lib/languages/applescript')); +// highlightJS.registerLanguage('arcade', require('highlight.js/lib/languages/arcade')); +highlightJS.registerLanguage('cpp', require('highlight.js/lib/languages/cpp')); +// highlightJS.registerLanguage('arduino', require('highlight.js/lib/languages/arduino')); +// highlightJS.registerLanguage('armasm', require('highlight.js/lib/languages/armasm')); +highlightJS.registerLanguage('xml', require('highlight.js/lib/languages/xml')); +// highlightJS.registerLanguage('asciidoc', require('highlight.js/lib/languages/asciidoc')); +// highlightJS.registerLanguage('aspectj', require('highlight.js/lib/languages/aspectj')); +// highlightJS.registerLanguage('autohotkey', require('highlight.js/lib/languages/autohotkey')); +// highlightJS.registerLanguage('autoit', require('highlight.js/lib/languages/autoit')); +// highlightJS.registerLanguage('avrasm', require('highlight.js/lib/languages/avrasm')); +highlightJS.registerLanguage('awk', require('highlight.js/lib/languages/awk')); +// highlightJS.registerLanguage('axapta', require('highlight.js/lib/languages/axapta')); +highlightJS.registerLanguage('bash', require('highlight.js/lib/languages/bash')); +// highlightJS.registerLanguage('basic', require('highlight.js/lib/languages/basic')); +// highlightJS.registerLanguage('bnf', require('highlight.js/lib/languages/bnf')); +// highlightJS.registerLanguage('brainfuck', require('highlight.js/lib/languages/brainfuck')); +// highlightJS.registerLanguage('cal', require('highlight.js/lib/languages/cal')); +// highlightJS.registerLanguage('capnproto', require('highlight.js/lib/languages/capnproto')); +// highlightJS.registerLanguage('ceylon', require('highlight.js/lib/languages/ceylon')); +// highlightJS.registerLanguage('clean', require('highlight.js/lib/languages/clean')); +highlightJS.registerLanguage('clojure', require('highlight.js/lib/languages/clojure')); +highlightJS.registerLanguage('clojure-repl', require('highlight.js/lib/languages/clojure-repl')); +highlightJS.registerLanguage('cmake', require('highlight.js/lib/languages/cmake')); +highlightJS.registerLanguage('coffeescript', require('highlight.js/lib/languages/coffeescript')); +// highlightJS.registerLanguage('coq', require('highlight.js/lib/languages/coq')); +// highlightJS.registerLanguage('cos', require('highlight.js/lib/languages/cos')); +// highlightJS.registerLanguage('crmsh', require('highlight.js/lib/languages/crmsh')); +highlightJS.registerLanguage('crystal', require('highlight.js/lib/languages/crystal')); +highlightJS.registerLanguage('cs', require('highlight.js/lib/languages/cs')); +highlightJS.registerLanguage('csp', require('highlight.js/lib/languages/csp')); +highlightJS.registerLanguage('css', require('highlight.js/lib/languages/css')); +highlightJS.registerLanguage('d', require('highlight.js/lib/languages/d')); +highlightJS.registerLanguage('markdown', require('highlight.js/lib/languages/markdown')); +highlightJS.registerLanguage('dart', require('highlight.js/lib/languages/dart')); +// highlightJS.registerLanguage('delphi', require('highlight.js/lib/languages/delphi')); +highlightJS.registerLanguage('diff', require('highlight.js/lib/languages/diff')); +highlightJS.registerLanguage('django', require('highlight.js/lib/languages/django')); +// highlightJS.registerLanguage('dns', require('highlight.js/lib/languages/dns')); +highlightJS.registerLanguage('dockerfile', require('highlight.js/lib/languages/dockerfile')); +// highlightJS.registerLanguage('dos', require('highlight.js/lib/languages/dos')); +// highlightJS.registerLanguage('dsconfig', require('highlight.js/lib/languages/dsconfig')); +// highlightJS.registerLanguage('dts', require('highlight.js/lib/languages/dts')); +// highlightJS.registerLanguage('dust', require('highlight.js/lib/languages/dust')); +// highlightJS.registerLanguage('ebnf', require('highlight.js/lib/languages/ebnf')); +highlightJS.registerLanguage('elixir', require('highlight.js/lib/languages/elixir')); +highlightJS.registerLanguage('elm', require('highlight.js/lib/languages/elm')); +highlightJS.registerLanguage('ruby', require('highlight.js/lib/languages/ruby')); +highlightJS.registerLanguage('erb', require('highlight.js/lib/languages/erb')); +highlightJS.registerLanguage('erlang-repl', require('highlight.js/lib/languages/erlang-repl')); +highlightJS.registerLanguage('erlang', require('highlight.js/lib/languages/erlang')); +highlightJS.registerLanguage('excel', require('highlight.js/lib/languages/excel')); +// highlightJS.registerLanguage('fix', require('highlight.js/lib/languages/fix')); +// highlightJS.registerLanguage('flix', require('highlight.js/lib/languages/flix')); +// highlightJS.registerLanguage('fortran', require('highlight.js/lib/languages/fortran')); +highlightJS.registerLanguage('fsharp', require('highlight.js/lib/languages/fsharp')); +// highlightJS.registerLanguage('gams', require('highlight.js/lib/languages/gams')); +// highlightJS.registerLanguage('gauss', require('highlight.js/lib/languages/gauss')); +// highlightJS.registerLanguage('gcode', require('highlight.js/lib/languages/gcode')); +// highlightJS.registerLanguage('gherkin', require('highlight.js/lib/languages/gherkin')); +// highlightJS.registerLanguage('glsl', require('highlight.js/lib/languages/glsl')); +// highlightJS.registerLanguage('gml', require('highlight.js/lib/languages/gml')); +highlightJS.registerLanguage('go', require('highlight.js/lib/languages/go')); +// highlightJS.registerLanguage('golo', require('highlight.js/lib/languages/golo')); +highlightJS.registerLanguage('gradle', require('highlight.js/lib/languages/gradle')); +highlightJS.registerLanguage('groovy', require('highlight.js/lib/languages/groovy')); +// highlightJS.registerLanguage('haml', require('highlight.js/lib/languages/haml')); +highlightJS.registerLanguage('handlebars', require('highlight.js/lib/languages/handlebars')); +highlightJS.registerLanguage('haskell', require('highlight.js/lib/languages/haskell')); +// highlightJS.registerLanguage('haxe', require('highlight.js/lib/languages/haxe')); +// highlightJS.registerLanguage('hsp', require('highlight.js/lib/languages/hsp')); +highlightJS.registerLanguage('htmlbars', require('highlight.js/lib/languages/htmlbars')); +highlightJS.registerLanguage('http', require('highlight.js/lib/languages/http')); +// highlightJS.registerLanguage('hy', require('highlight.js/lib/languages/hy')); +// highlightJS.registerLanguage('inform7', require('highlight.js/lib/languages/inform7')); +highlightJS.registerLanguage('ini', require('highlight.js/lib/languages/ini')); +// highlightJS.registerLanguage('irpf90', require('highlight.js/lib/languages/irpf90')); +// highlightJS.registerLanguage('isbl', require('highlight.js/lib/languages/isbl')); +highlightJS.registerLanguage('java', require('highlight.js/lib/languages/java')); +highlightJS.registerLanguage('javascript', require('highlight.js/lib/languages/javascript')); +// highlightJS.registerLanguage('jboss-cli', require('highlight.js/lib/languages/jboss-cli')); +highlightJS.registerLanguage('json', require('highlight.js/lib/languages/json')); +highlightJS.registerLanguage('julia', require('highlight.js/lib/languages/julia')); +highlightJS.registerLanguage('julia-repl', require('highlight.js/lib/languages/julia-repl')); +highlightJS.registerLanguage('kotlin', require('highlight.js/lib/languages/kotlin')); +// highlightJS.registerLanguage('lasso', require('highlight.js/lib/languages/lasso')); +// highlightJS.registerLanguage('ldif', require('highlight.js/lib/languages/ldif')); +// highlightJS.registerLanguage('leaf', require('highlight.js/lib/languages/leaf')); +highlightJS.registerLanguage('less', require('highlight.js/lib/languages/less')); +highlightJS.registerLanguage('lisp', require('highlight.js/lib/languages/lisp')); +// highlightJS.registerLanguage('livecodeserver', require('highlight.js/lib/languages/livecodeserver')); +// highlightJS.registerLanguage('livescript', require('highlight.js/lib/languages/livescript')); +highlightJS.registerLanguage('llvm', require('highlight.js/lib/languages/llvm')); +// highlightJS.registerLanguage('lsl', require('highlight.js/lib/languages/lsl')); +highlightJS.registerLanguage('lua', require('highlight.js/lib/languages/lua')); +highlightJS.registerLanguage('makefile', require('highlight.js/lib/languages/makefile')); +highlightJS.registerLanguage('mathematica', require('highlight.js/lib/languages/mathematica')); +highlightJS.registerLanguage('matlab', require('highlight.js/lib/languages/matlab')); +// highlightJS.registerLanguage('maxima', require('highlight.js/lib/languages/maxima')); +// highlightJS.registerLanguage('mel', require('highlight.js/lib/languages/mel')); +// highlightJS.registerLanguage('mercury', require('highlight.js/lib/languages/mercury')); +// highlightJS.registerLanguage('mipsasm', require('highlight.js/lib/languages/mipsasm')); +// highlightJS.registerLanguage('mizar', require('highlight.js/lib/languages/mizar')); +highlightJS.registerLanguage('perl', require('highlight.js/lib/languages/perl')); +// highlightJS.registerLanguage('mojolicious', require('highlight.js/lib/languages/mojolicious')); +// highlightJS.registerLanguage('monkey', require('highlight.js/lib/languages/monkey')); +// highlightJS.registerLanguage('moonscript', require('highlight.js/lib/languages/moonscript')); +// highlightJS.registerLanguage('n1ql', require('highlight.js/lib/languages/n1ql')); +highlightJS.registerLanguage('nginx', require('highlight.js/lib/languages/nginx')); +// highlightJS.registerLanguage('nimrod', require('highlight.js/lib/languages/nimrod')); +highlightJS.registerLanguage('nix', require('highlight.js/lib/languages/nix')); +// highlightJS.registerLanguage('nsis', require('highlight.js/lib/languages/nsis')); +highlightJS.registerLanguage('objectivec', require('highlight.js/lib/languages/objectivec')); +highlightJS.registerLanguage('ocaml', require('highlight.js/lib/languages/ocaml')); +// highlightJS.registerLanguage('openscad', require('highlight.js/lib/languages/openscad')); +// highlightJS.registerLanguage('oxygene', require('highlight.js/lib/languages/oxygene')); +// highlightJS.registerLanguage('parser3', require('highlight.js/lib/languages/parser3')); +// highlightJS.registerLanguage('pf', require('highlight.js/lib/languages/pf')); +highlightJS.registerLanguage('pgsql', require('highlight.js/lib/languages/pgsql')); +highlightJS.registerLanguage('php', require('highlight.js/lib/languages/php')); +highlightJS.registerLanguage('plaintext', require('highlight.js/lib/languages/plaintext')); +// highlightJS.registerLanguage('pony', require('highlight.js/lib/languages/pony')); +highlightJS.registerLanguage('powershell', require('highlight.js/lib/languages/powershell')); +// highlightJS.registerLanguage('processing', require('highlight.js/lib/languages/processing')); +// highlightJS.registerLanguage('profile', require('highlight.js/lib/languages/profile')); +// highlightJS.registerLanguage('prolog', require('highlight.js/lib/languages/prolog')); +highlightJS.registerLanguage('properties', require('highlight.js/lib/languages/properties')); +highlightJS.registerLanguage('protobuf', require('highlight.js/lib/languages/protobuf')); +highlightJS.registerLanguage('puppet', require('highlight.js/lib/languages/puppet')); +// highlightJS.registerLanguage('purebasic', require('highlight.js/lib/languages/purebasic')); +highlightJS.registerLanguage('python', require('highlight.js/lib/languages/python')); +// highlightJS.registerLanguage('q', require('highlight.js/lib/languages/q')); +// highlightJS.registerLanguage('qml', require('highlight.js/lib/languages/qml')); +highlightJS.registerLanguage('r', require('highlight.js/lib/languages/r')); +highlightJS.registerLanguage('reasonml', require('highlight.js/lib/languages/reasonml')); +// highlightJS.registerLanguage('rib', require('highlight.js/lib/languages/rib')); +// highlightJS.registerLanguage('roboconf', require('highlight.js/lib/languages/roboconf')); +// highlightJS.registerLanguage('routeros', require('highlight.js/lib/languages/routeros')); +// highlightJS.registerLanguage('rsl', require('highlight.js/lib/languages/rsl')); +// highlightJS.registerLanguage('ruleslanguage', require('highlight.js/lib/languages/ruleslanguage')); +highlightJS.registerLanguage('rust', require('highlight.js/lib/languages/rust')); +// highlightJS.registerLanguage('sas', require('highlight.js/lib/languages/sas')); +highlightJS.registerLanguage('scala', require('highlight.js/lib/languages/scala')); +highlightJS.registerLanguage('scheme', require('highlight.js/lib/languages/scheme')); +// highlightJS.registerLanguage('scilab', require('highlight.js/lib/languages/scilab')); +highlightJS.registerLanguage('scss', require('highlight.js/lib/languages/scss')); +highlightJS.registerLanguage('shell', require('highlight.js/lib/languages/shell')); +// highlightJS.registerLanguage('smali', require('highlight.js/lib/languages/smali')); +// highlightJS.registerLanguage('smalltalk', require('highlight.js/lib/languages/smalltalk')); +// highlightJS.registerLanguage('sml', require('highlight.js/lib/languages/sml')); +// highlightJS.registerLanguage('sqf', require('highlight.js/lib/languages/sqf')); +highlightJS.registerLanguage('sql', require('highlight.js/lib/languages/sql')); +// highlightJS.registerLanguage('stan', require('highlight.js/lib/languages/stan')); +// highlightJS.registerLanguage('stata', require('highlight.js/lib/languages/stata')); +// highlightJS.registerLanguage('step21', require('highlight.js/lib/languages/step21')); +highlightJS.registerLanguage('stylus', require('highlight.js/lib/languages/stylus')); +// highlightJS.registerLanguage('subunit', require('highlight.js/lib/languages/subunit')); +highlightJS.registerLanguage('swift', require('highlight.js/lib/languages/swift')); +// highlightJS.registerLanguage('taggerscript', require('highlight.js/lib/languages/taggerscript')); +highlightJS.registerLanguage('yaml', require('highlight.js/lib/languages/yaml')); +// highlightJS.registerLanguage('tap', require('highlight.js/lib/languages/tap')); +// highlightJS.registerLanguage('tcl', require('highlight.js/lib/languages/tcl')); +highlightJS.registerLanguage('tex', require('highlight.js/lib/languages/tex')); +// highlightJS.registerLanguage('thrift', require('highlight.js/lib/languages/thrift')); +// highlightJS.registerLanguage('tp', require('highlight.js/lib/languages/tp')); +// highlightJS.registerLanguage('twig', require('highlight.js/lib/languages/twig')); +highlightJS.registerLanguage('typescript', require('highlight.js/lib/languages/typescript')); +// highlightJS.registerLanguage('vala', require('highlight.js/lib/languages/vala')); +// highlightJS.registerLanguage('vbnet', require('highlight.js/lib/languages/vbnet')); +// highlightJS.registerLanguage('vbscript', require('highlight.js/lib/languages/vbscript')); +// highlightJS.registerLanguage('vbscript-html', require('highlight.js/lib/languages/vbscript-html')); +// highlightJS.registerLanguage('verilog', require('highlight.js/lib/languages/verilog')); +// highlightJS.registerLanguage('vhdl', require('highlight.js/lib/languages/vhdl')); +highlightJS.registerLanguage('vim', require('highlight.js/lib/languages/vim')); +// highlightJS.registerLanguage('x86asm', require('highlight.js/lib/languages/x86asm')); +// highlightJS.registerLanguage('xl', require('highlight.js/lib/languages/xl')); +// highlightJS.registerLanguage('xquery', require('highlight.js/lib/languages/xquery')); +// highlightJS.registerLanguage('zephir', require('highlight.js/lib/languages/zephir')); + +export const hljs: HighlightJS = highlightJS as HighlightJS; diff --git a/src/utils.ts b/src/utils.ts index 649f23a..43462bd 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,40 +1,40 @@ const specials = [ // Order matters for these - "-", - "[", - "]", + '-', + '[', + ']', // Order doesn't matter for any of these - "/", - "{", - "}", - "(", - ")", - "*", - "+", - "?", - ".", - "\\", - "^", - "$", - "|" + '/', + '{', + '}', + '(', + ')', + '*', + '+', + '?', + '.', + '\\', + '^', + '$', + '|', ]; // All characters will be escaped with '\' // even though only some strictly require it when inside of [] -const regex = RegExp("[" + specials.join("\\") + "]", "g"); +const regex = RegExp('[' + specials.join('\\') + ']', 'g'); /** * Escapes all required characters for safe usage inside a RegExp */ export function escapeForRegExp(str: string): string { - return str.replace(regex, "\\$&"); + return str.replace(regex, '\\$&'); } /** * Converts all '\' in @path to unix style '/' */ export function unifyPath(path: string): string { - return path ? path.replace(/\\/g, "/") : path; + return path ? path.replace(/\\/g, '/') : path; } /** diff --git a/typings/merge.d.ts b/typings/merge.d.ts index 9881682..52aef96 100644 --- a/typings/merge.d.ts +++ b/typings/merge.d.ts @@ -1,3 +1,3 @@ -declare module "merge" { +declare module 'merge' { export function recursive(clone: boolean, ...items: object[]): object; } diff --git a/webpack.bundles.ts b/webpack.bundles.ts index 61d1896..8852ac8 100644 --- a/webpack.bundles.ts +++ b/webpack.bundles.ts @@ -1,60 +1,61 @@ -import path from "path"; +import path from 'path'; -import webpack from "webpack"; - -const minimize = process.env.WEBPACK_MINIFY === "true"; +import webpack from 'webpack'; const diff2htmlBrowserConfig: webpack.Configuration = { - mode: "production", - optimization: { minimize: minimize }, module: { rules: [ { test: /\.tsx?$/, - use: "ts-loader", - exclude: /node_modules/ - } - ] + use: 'ts-loader', + exclude: /node_modules/, + }, + ], }, resolve: { - extensions: [".tsx", ".ts", ".jsx", ".js"] + extensions: ['.tsx', '.ts', '.jsx', '.js'], }, - entry: "./src/diff2html.ts", + entry: './src/diff2html.ts', output: { - path: path.resolve(__dirname, "bundles/js"), - libraryTarget: "umd", - globalObject: "this", - library: "Diff2Html", - filename: `diff2html${minimize ? ".min" : ""}.js`, - umdNamedDefine: true - } + path: path.resolve(__dirname, 'bundles/js'), + libraryTarget: 'umd', + globalObject: 'this', + library: 'Diff2Html', + filename: 'diff2html.min.js', + umdNamedDefine: true, + }, }; -const diff2htmlUIBrowserConfig: webpack.Configuration = { - mode: "production", - optimization: { minimize: minimize }, - module: { - rules: [ - { - test: /\.tsx?$/, - use: "ts-loader", - exclude: /node_modules/ - } - ] - }, - resolve: { - extensions: [".tsx", ".ts", ".jsx", ".js"] - }, - entry: "./src/ui/js/diff2html-ui.ts", - output: { - path: path.resolve(__dirname, "bundles/js"), - libraryTarget: "umd", - globalObject: "this", - filename: `diff2html-ui${minimize ? ".min" : ""}.js`, - umdNamedDefine: true - } -}; +function diff2htmlUIBrowserConfig(entrypointName: string): webpack.Configuration { + return { + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/, + }, + ], + }, + resolve: { + extensions: ['.tsx', '.ts', '.jsx', '.js'], + }, + entry: `./src/ui/js/${entrypointName}.ts`, + output: { + path: path.resolve(__dirname, 'bundles/js'), + libraryTarget: 'umd', + globalObject: 'this', + filename: `${entrypointName}.min.js`, + umdNamedDefine: true, + }, + }; +} -const config: webpack.Configuration[] = [diff2htmlBrowserConfig, diff2htmlUIBrowserConfig]; +const config: webpack.Configuration[] = [ + diff2htmlBrowserConfig, + diff2htmlUIBrowserConfig('diff2html-ui'), + diff2htmlUIBrowserConfig('diff2html-ui-slim'), + diff2htmlUIBrowserConfig('diff2html-ui-base'), +]; export default config; diff --git a/webpack.website.ts b/webpack.website.ts index f8a6b9a..3986436 100644 --- a/webpack.website.ts +++ b/webpack.website.ts @@ -1,140 +1,116 @@ -import path from "path"; +import path from 'path'; -import webpack from "webpack"; -import { Plugin } from "postcss"; -import HtmlWebpackPlugin from "html-webpack-plugin"; -import MiniCssExtractPlugin from "mini-css-extract-plugin"; -import autoprefixer from "autoprefixer"; -import CopyWebpackPlugin from "copy-webpack-plugin"; +import webpack from 'webpack'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import MiniCssExtractPlugin from 'mini-css-extract-plugin'; +import CopyWebpackPlugin from 'copy-webpack-plugin'; -const isDevelopment = process.env.NODE_ENV !== "production"; -const minimize = process.env.WEBPACK_MINIFY === "true"; - -const pages = ["index", "demo"]; +const pages = ['index', 'demo']; const config: webpack.Configuration[] = pages.map(page => { return { devServer: { port: 3000, open: true, - contentBase: path.join(__dirname, "./website") + contentBase: path.join(__dirname, './website'), }, entry: { - [page]: `./website/templates/pages/${page}/${page}.ts` + [page]: `./website/templates/pages/${page}/${page}.ts`, }, output: { - path: path.resolve(__dirname, "./docs") + path: path.resolve(__dirname, './docs'), }, resolve: { - extensions: [".tsx", ".ts", ".jsx", ".js"] + extensions: ['.tsx', '.ts', '.jsx', '.js'], }, - optimization: { minimize }, module: { rules: [ { test: /\.tsx?$/, - use: "ts-loader", - exclude: /node_modules/ + use: 'ts-loader', + exclude: /node_modules/, }, { test: /\.handlebars$/, - loader: "handlebars-loader", + loader: 'handlebars-loader', options: { precompileOptions: { - knownHelpersOnly: false + knownHelpersOnly: false, }, - helperDirs: [path.join(__dirname, "website/templates/helpers")], - partialDirs: [path.join(__dirname, "website/templates")] - } + helperDirs: [path.join(__dirname, 'website/templates/helpers')], + partialDirs: [path.join(__dirname, 'website/templates')], + }, }, { test: /\.(css)$/, - use: [ - MiniCssExtractPlugin.loader, - { - loader: "css-loader", - options: { - sourceMap: isDevelopment - } - }, - { - loader: "postcss-loader", - options: { - autoprefixer: { - browsers: ["last 2 versions"] - }, - sourceMap: isDevelopment, - plugins: (): Plugin[] => [autoprefixer] - } - } - ] + use: [MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader'], }, { test: /\.(html)$/, use: { - loader: "html-loader", + loader: 'html-loader', options: { - attrs: ["img:src"] - } - } + attrs: ['img:src'], + }, + }, }, { - test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, + test: /\.woff(2)?(\?v=\d\.\d\.\d)?$/, use: [ { - loader: "url-loader", + loader: 'url-loader', options: { limit: 1000, - mimetype: "application/font-woff" - } - } - ] + mimetype: 'application/font-woff', + }, + }, + ], }, { - test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, - loader: "file-loader" + test: /\.(ttf|eot|svg)(\?v=\d\.\d\.\d)?$/, + loader: 'file-loader', }, { test: /\.(jpeg|jpg|png|gif)$/, use: [ { - loader: "file-loader", + loader: 'file-loader', options: { - name: "[name].[ext]", - outputPath: "images/", - useRelativePath: true - } + name: '[name].[ext]', + outputPath: 'images/', + useRelativePath: true, + }, }, { - loader: "image-webpack-loader", + loader: 'image-webpack-loader', options: { mozjpeg: { progressive: true, - quality: 65 + quality: 65, }, optipng: { - enabled: true + enabled: true, }, pngquant: { quality: [0.65, 0.9], - speed: 4 + speed: 4, }, gifsicle: { - interlaced: false + interlaced: false, }, webp: { - quality: 75 - } - } - } - ] - } - ] + quality: 75, + }, + }, + }, + ], + }, + ], }, plugins: [ new MiniCssExtractPlugin({ - filename: "[name].css", - chunkFilename: "[id].css" + filename: '[name].css', + chunkFilename: '[id].css', }), new HtmlWebpackPlugin({ hash: true, @@ -142,7 +118,7 @@ const config: webpack.Configuration[] = pages.map(page => { title: `${page} page`, filename: `${page}.html`, template: `./website/templates/pages/${page}/${page}.handlebars`, - minify: !isDevelopment && { + minify: { html5: true, collapseWhitespace: true, caseSensitive: true, @@ -155,15 +131,15 @@ const config: webpack.Configuration[] = pages.map(page => { keepClosingSlash: true, minifyJS: true, minifyCSS: true, - minifyURLs: true - } + minifyURLs: true, + }, }), new CopyWebpackPlugin([ - { from: "website/favicon.ico", to: "favicon.ico" }, - { from: "website/robots.txt", to: "robots.txt" }, - { from: "website/sitemap.xml", to: "sitemap.xml" } - ]) - ] + { from: 'website/favicon.ico', to: 'favicon.ico' }, + { from: 'website/robots.txt', to: 'robots.txt' }, + { from: 'website/sitemap.xml', to: 'sitemap.xml' }, + ]), + ], }; }); diff --git a/website/main.css b/website/main.css index 0d3ad50..ac20626 100644 --- a/website/main.css +++ b/website/main.css @@ -17,11 +17,11 @@ } .m-b-md { - margin-bottom: 23px !important + margin-bottom: 23px !important; } .p-t { - padding-top: 15px !important + padding-top: 15px !important; } @media (min-width: 768px) { @@ -34,8 +34,8 @@ .btn { display: inline-block; color: #fff; - background: #26A65B; - font-weight: 400 + background: #26a65b; + font-weight: 400; } .btn:hover { @@ -67,19 +67,19 @@ padding: 40px 0; text-align: center; font-size: 14px; - border-top: 1px solid #dcdfe4 + border-top: 1px solid #dcdfe4; } .footer p { - margin-bottom: 5px + margin-bottom: 5px; } .footer a { - color: #26A65B; + color: #26a65b; } .container a { - color: #26A65B; + color: #26a65b; } .container a.btn { @@ -87,11 +87,11 @@ } .footer-list-item { - display: inline-block + display: inline-block; } .footer-list-item:not(:last-child):after { - content: "\b7" + content: '\b7'; } .footer > ul { @@ -116,7 +116,7 @@ } .row-bordered { - position: relative + position: relative; } .row-bordered:before { @@ -129,14 +129,14 @@ margin-left: -40%; height: 1px; background: -webkit-radial-gradient(ellipse at center, rgba(0, 0, 0, 0.2) 0, rgba(255, 255, 255, 0) 75%); - background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.2) 0, rgba(255, 255, 255, 0) 75%) + background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.2) 0, rgba(255, 255, 255, 0) 75%); } .hero { position: relative; text-align: center; padding: 80px 0; - border-bottom: 1px solid #dcdfe4 + border-bottom: 1px solid #dcdfe4; } .hero-booticon { @@ -159,7 +159,7 @@ } .hero-homepage > .btn { - margin-top: 20px + margin-top: 20px; } .swag-line:before { @@ -171,9 +171,9 @@ right: 0; height: 5px; z-index: 2; - background-color: #26A65B; - background: -webkit-linear-gradient(45deg, #28a142, #26A65B); - background: linear-gradient(45deg, #28a142, #26A65B) + background-color: #26a65b; + background: -webkit-linear-gradient(45deg, #28a142, #26a65b); + background: linear-gradient(45deg, #28a142, #26a65b); } .navbar { @@ -182,7 +182,7 @@ } .navbar-header { - text-align: center + text-align: center; } .navbar-brand { @@ -192,21 +192,26 @@ display: inline-block; float: none; text-align: center; - margin: 5px 0 0 + margin: 5px 0 0; } .navbar-nav { - margin-right: -15px + margin-right: -15px; } .navbar-nav > li > a { - font-size: 14px + font-size: 14px; } -.navbar-default .navbar-brand, .navbar-default .navbar-brand:focus, .navbar-default .navbar-brand:hover, .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:focus, .navbar-default .navbar-nav > li > a:hover { +.navbar-default .navbar-brand, +.navbar-default .navbar-brand:focus, +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-nav > li > a, +.navbar-default .navbar-nav > li > a:focus, +.navbar-default .navbar-nav > li > a:hover { background: transparent; color: #293a46; - font-weight: 300 + font-weight: 300; } .navbar-default .navbar-toggle { @@ -215,88 +220,94 @@ top: 7px; border-color: #fff; color: #293a46; - margin-right: 0 + margin-right: 0; } -.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { background: #f9f9f9; - border-color: #f9f9f9 + border-color: #f9f9f9; } @media (min-width: 768px) { .navbar-full .navbar-brand { - margin-left: -25px + margin-left: -25px; } .navbar-tall { - height: 125px + height: 125px; } - .navbar-tall .navbar-header, .navbar-tall .navbar-nav { + .navbar-tall .navbar-header, + .navbar-tall .navbar-nav { line-height: 125px; - text-align: left + text-align: left; } .navbar-brand { float: none; display: inline-block; text-align: left; - margin: 0 + margin: 0; } .navbar-nav > li > a { display: inline-block; - margin-left: 13px + margin-left: 13px; } .navbar-nav > li:first-child > a { - margin-left: 0 + margin-left: 0; } - } body { font-size: 16px; font-family: Roboto, sans-serif; font-weight: 300; - line-height: 1.6 + line-height: 1.6; } h1 { font-size: 26px; - font-weight: 300 + font-weight: 300; } h2 { font-size: 18px; - font-weight: 300 + font-weight: 300; } h3 { font-size: 26px; - font-weight: 300 + font-weight: 300; } h4 { font-size: 16px; - font-weight: 300 + font-weight: 300; } h5 { font-size: 16px; - font-weight: 400 + font-weight: 400; } -h1, h2, h3, h4, h5 { - line-height: 1.4 +h1, +h2, +h3, +h4, +h5 { + line-height: 1.4; } -h1, h2 { - margin: 10px 0 +h1, +h2 { + margin: 10px 0; } h5 { - margin: 6px 0 + margin: 6px 0; } @media (min-width: 768px) { @@ -304,33 +315,33 @@ h5 { font-size: 16px; font-family: Roboto, sans-serif; font-weight: 300; - line-height: 1.6 + line-height: 1.6; } h1 { font-size: 38px; - font-weight: 300 + font-weight: 300; } h2 { font-size: 26px; font-weight: 300; - line-height: 1.4 + line-height: 1.4; } h3 { font-size: 26px; - font-weight: 300 + font-weight: 300; } h4 { font-size: 18px; - font-weight: 300 + font-weight: 300; } h5 { font-size: 16px; - font-weight: 400 + font-weight: 400; } } @@ -343,7 +354,8 @@ a { color: inherit; } -a:hover, a:focus { +a:hover, +a:focus { text-decoration: underline; } @@ -357,40 +369,42 @@ a:hover, a:focus { } .text-muted { - color: #697176 + color: #697176; } .template-index h3 { font-size: 21px; - margin-bottom: 12px + margin-bottom: 12px; } .template-index h4 { color: #697176; - line-height: 1.6 + line-height: 1.6; } -.template-index h4 a, .template-index p a { - color: #26A65B; +.template-index h4 a, +.template-index p a { + color: #26a65b; } .template-index h5 { font-size: 17px; - margin-bottom: 8px + margin-bottom: 8px; } -.homepage-terminal-example, .homepage-code-example { +.homepage-terminal-example, +.homepage-code-example { position: relative; font-family: monospace; background: #272b38; color: #48d8a0; border-radius: 8px; - padding: 30px + padding: 30px; } .homepage-terminal-example .text-muted, .homepage-code-example .text-muted { - color: #6a7490 + color: #6a7490; } @media (min-width: 768px) { @@ -408,7 +422,7 @@ a:hover, a:focus { } .hero-green { - color: #26A65B; + color: #26a65b; } .hero-black { @@ -416,7 +430,7 @@ a:hover, a:focus { } .hero-red { - color: #CB2C37; + color: #cb2c37; } .svg-icon-large { diff --git a/website/main.ts b/website/main.ts index 3521668..31753d9 100644 --- a/website/main.ts +++ b/website/main.ts @@ -1 +1 @@ -import "bootstrap/dist/css/bootstrap.css"; +import 'bootstrap/dist/css/bootstrap.css'; diff --git a/website/templates/helpers/block.ts b/website/templates/helpers/block.ts index 192a61c..dc44bbd 100644 --- a/website/templates/helpers/block.ts +++ b/website/templates/helpers/block.ts @@ -1,8 +1,8 @@ -import handlebars, { HelperOptions } from "handlebars"; +import handlebars, { HelperOptions } from 'handlebars'; const loadPartial = (name: string): handlebars.Template => { let partial = handlebars.partials[name]; - if (typeof partial === "string") { + if (typeof partial === 'string') { partial = handlebars.compile(partial); handlebars.partials[name] = partial; } diff --git a/website/templates/helpers/partial.ts b/website/templates/helpers/partial.ts index 108eba3..7b5df58 100644 --- a/website/templates/helpers/partial.ts +++ b/website/templates/helpers/partial.ts @@ -1,4 +1,4 @@ -import handlebars, { HelperOptions } from "handlebars"; +import handlebars, { HelperOptions } from 'handlebars'; export default (name: string, options: HelperOptions): void => { handlebars.registerPartial(name, options.fn); diff --git a/website/templates/pages/demo/demo.css b/website/templates/pages/demo/demo.css deleted file mode 100644 index 72ef256..0000000 --- a/website/templates/pages/demo/demo.css +++ /dev/null @@ -1 +0,0 @@ -@import url("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/github.min.css"); diff --git a/website/templates/pages/demo/demo.ts b/website/templates/pages/demo/demo.ts index 30730e9..7c271fd 100644 --- a/website/templates/pages/demo/demo.ts +++ b/website/templates/pages/demo/demo.ts @@ -1,9 +1,9 @@ -import { Diff2HtmlUI, defaultDiff2HtmlUIConfig, Diff2HtmlUIConfig } from "../../../../src/ui/js/diff2html-ui"; +import { Diff2HtmlUI, defaultDiff2HtmlUIConfig, Diff2HtmlUIConfig } from '../../../../src/ui/js/diff2html-ui-slim'; -import "../../../main.ts"; -import "../../../main.css"; -import "./demo.css"; -import "../../../../src/ui/css/diff2html.css"; +import '../../../main.ts'; +import '../../../main.css'; +import 'highlight.js/styles/github.css'; +import '../../../../src/ui/css/diff2html.css'; /* * Example URLs: @@ -23,18 +23,18 @@ type URLParams = { [key: string]: string | boolean | number | undefined; }; -const searchParam = "diff"; +const searchParam = 'diff'; function getParamsFromSearch(search: string): URLParams { try { return search - .split("?")[1] - .split("&") + .split('?')[1] + .split('&') .reduce((urlParams, e) => { - const values = e.split("="); + const values = e.split('='); return { ...urlParams, - [values[0]]: values[1] + [values[0]]: values[1], }; }, {}); } catch (_ignore) { @@ -43,8 +43,8 @@ function getParamsFromSearch(search: string): URLParams { } function validateUrl(url: string): boolean { - return /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( - url + return /^(?:(?:https?|ftp):)?\/\/(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[01])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4])|(?:[\da-z\u00a1-\uffff]-*)*[\da-z\u00a1-\uffff]+(?:\.(?:[\da-z\u00a1-\uffff]-*)*[\da-z\u00a1-\uffff]+)*\.[a-z\u00a1-\uffff]{2,}.?)(?::\d{2,5})?(?:[#/?]\S*)?$/i.test( + url, ); } @@ -55,7 +55,7 @@ type Request = { function prepareRequest(url: string): Request { if (!validateUrl(url)) { - const errorMsg = "Invalid url provided!"; + const errorMsg = 'Invalid url provided!'; console.error(errorMsg); throw new Error(errorMsg); } @@ -74,44 +74,44 @@ function prepareRequest(url: string): Request { function gitLabUrlGen(userName: string, projectName: string, type: string, value: string): string { return ( - "https://crossorigin.me/https://gitlab.com/" + userName + "/" + projectName + "/" + type + "/" + value + ".diff" + 'https://crossorigin.me/https://gitlab.com/' + userName + '/' + projectName + '/' + type + '/' + value + '.diff' ); } function gitHubUrlGen(userName: string, projectName: string, type: string, value: string): string { - headers.append("Accept", "application/vnd.github.v3.diff"); - return "https://api.github.com/repos/" + userName + "/" + projectName + "/" + type + "/" + value; + headers.append('Accept', 'application/vnd.github.v3.diff'); + return 'https://api.github.com/repos/' + userName + '/' + projectName + '/' + type + '/' + value; } function bitbucketUrlGen(userName: string, projectName: string, type: string, value: string): string { - const baseUrl = "https://bitbucket.org/api/2.0/repositories/"; - if (type === "pullrequests") { - return baseUrl + userName + "/" + projectName + "/pullrequests/" + value + "/diff"; + const baseUrl = 'https://bitbucket.org/api/2.0/repositories/'; + if (type === 'pullrequests') { + return baseUrl + userName + '/' + projectName + '/pullrequests/' + value + '/diff'; } - return baseUrl + userName + "/" + projectName + "/diff/" + value; + return baseUrl + userName + '/' + projectName + '/diff/' + value; } let values; if ((values = githubCommitUrl.exec(url))) { - fetchUrl = gitHubUrlGen(values[1], values[2], "commits", values[3]); + fetchUrl = gitHubUrlGen(values[1], values[2], 'commits', values[3]); } else if ((values = githubPrUrl.exec(url))) { - fetchUrl = gitHubUrlGen(values[1], values[2], "pulls", values[3]); + fetchUrl = gitHubUrlGen(values[1], values[2], 'pulls', values[3]); } else if ((values = gitlabCommitUrl.exec(url))) { - fetchUrl = gitLabUrlGen(values[1], values[2], "commit", values[3]); + fetchUrl = gitLabUrlGen(values[1], values[2], 'commit', values[3]); } else if ((values = gitlabPrUrl.exec(url))) { - fetchUrl = gitLabUrlGen(values[1], values[2], "merge_requests", values[3]); + fetchUrl = gitLabUrlGen(values[1], values[2], 'merge_requests', values[3]); } else if ((values = bitbucketCommitUrl.exec(url))) { - fetchUrl = bitbucketUrlGen(values[1], values[2], "commit", values[3]); + fetchUrl = bitbucketUrlGen(values[1], values[2], 'commit', values[3]); } else if ((values = bitbucketPrUrl.exec(url))) { - fetchUrl = bitbucketUrlGen(values[1], values[2], "pullrequests", values[3]); + fetchUrl = bitbucketUrlGen(values[1], values[2], 'pullrequests', values[3]); } else { - console.info("Could not parse url, using the provided url."); - fetchUrl = "https://crossorigin.me/" + url; + console.info('Could not parse url, using the provided url.'); + fetchUrl = 'https://crossorigin.me/' + url; } return { url: fetchUrl, - headers: headers + headers: headers, }; } @@ -121,13 +121,13 @@ function getConfiguration(urlParams: URLParams): Diff2HtmlUIConfig { const { diff, ...urlParamsRest } = urlParams; const config: URLParams = { ...defaultDiff2HtmlUIConfig, - ...urlParamsRest + ...urlParamsRest, }; return Object.entries(config).reduce((object, [k, v]) => { const newObject = !Number.isNaN(Number(v)) ? { [k]: Number(v) } - : v === "true" || v === "false" + : v === 'true' || v === 'false' ? { [k]: Boolean(v) } : { [k]: v }; return { ...object, ...newObject }; @@ -137,14 +137,14 @@ function getConfiguration(urlParams: URLParams): Diff2HtmlUIConfig { async function getDiff(request: Request): Promise { try { const result = await fetch(request.url, { - method: "GET", + method: 'GET', headers: request.headers, - mode: "cors", - cache: "default" + mode: 'cors', + cache: 'default', }); return result.text(); } catch (error) { - console.error("Failed to retrieve diff", error); + console.error('Failed to retrieve diff', error); throw error; } } @@ -152,10 +152,10 @@ async function getDiff(request: Request): Promise { function draw(diffString: string, config: Diff2HtmlUIConfig, elements: Elements): void { const diff2htmlUi = new Diff2HtmlUI(diffString, elements.structure.diffTarget, config); - if (config.outputFormat === "side-by-side") { - elements.structure.container.style.width = "100%"; + if (config.outputFormat === 'side-by-side') { + elements.structure.container.style.width = '100%'; } else { - elements.structure.container.style.width = ""; + elements.structure.container.style.width = ''; } diff2htmlUi.draw(); @@ -163,7 +163,7 @@ function draw(diffString: string, config: Diff2HtmlUIConfig, elements: Elements) async function prepareInitialState(elements: Elements): Promise<[Diff2HtmlUIConfig, string]> { const urlParams = getParamsFromSearch(window.location.search); - const currentUrl = (urlParams && urlParams[searchParam]) || "https://github.com/rtfpessoa/diff2html/pull/106"; + const currentUrl = (urlParams && urlParams[searchParam]) || 'https://github.com/rtfpessoa/diff2html/pull/106'; if (currentUrl !== elements.url.input.value) elements.url.input.value = currentUrl; @@ -178,20 +178,20 @@ async function prepareInitialState(elements: Elements): Promise<[Diff2HtmlUIConf function updateBrowserUrl(config: Diff2HtmlUIConfig, newDiffUrl: string): void { if (history.pushState) { const paramString = Object.entries(config) - .map(([k, v]) => k + "=" + v) - .join("&"); + .map(([k, v]) => k + '=' + v) + .join('&'); const newPageUrl = window.location.protocol + - "//" + + '//' + window.location.host + window.location.pathname + - "?" + + '?' + paramString + - "&" + + '&' + searchParam + - "=" + + '=' + newDiffUrl; - window.history.pushState({ path: newPageUrl }, "", newPageUrl); + window.history.pushState({ path: newPageUrl }, '', newPageUrl); } } @@ -215,15 +215,15 @@ type Elements = { }; }; -document.addEventListener("DOMContentLoaded", async () => { +document.addEventListener('DOMContentLoaded', async () => { // Improves browser compatibility - require("whatwg-fetch"); + require('whatwg-fetch'); const drawAndUpdateUrl = async ( diffUrl: string, diffString: string, config: Diff2HtmlUIConfig, - elements: Elements + elements: Elements, ): Promise => { updateBrowserUrl(config, diffUrl); const newRequest = prepareRequest(diffUrl); @@ -233,22 +233,22 @@ document.addEventListener("DOMContentLoaded", async () => { const elements: Elements = { structure: { - container: document.getElementsByClassName("container")[0] as HTMLElement, - diffTarget: document.getElementById("url-diff-container") as HTMLElement + container: document.getElementsByClassName('container')[0] as HTMLElement, + diffTarget: document.getElementById('url-diff-container') as HTMLElement, }, url: { - input: document.getElementById("url") as HTMLInputElement, - button: document.getElementById("url-btn") as HTMLElement + input: document.getElementById('url') as HTMLInputElement, + button: document.getElementById('url-btn') as HTMLElement, }, options: { - outputFormat: document.getElementById("diff-url-options-output-format") as HTMLInputElement, - matching: document.getElementById("diff-url-options-matching") as HTMLInputElement, - wordsThreshold: document.getElementById("diff-url-options-match-words-threshold") as HTMLInputElement, - matchingMaxComparisons: document.getElementById("diff-url-options-matching-max-comparisons") as HTMLInputElement + outputFormat: document.getElementById('diff-url-options-output-format') as HTMLInputElement, + matching: document.getElementById('diff-url-options-matching') as HTMLInputElement, + wordsThreshold: document.getElementById('diff-url-options-match-words-threshold') as HTMLInputElement, + matchingMaxComparisons: document.getElementById('diff-url-options-matching-max-comparisons') as HTMLInputElement, }, checkboxes: { - drawFileList: document.getElementById("diff-url-options-show-files") as HTMLInputElement - } + drawFileList: document.getElementById('diff-url-options-show-files') as HTMLInputElement, + }, }; let [config, diffString] = await prepareInitialState(elements); @@ -262,20 +262,20 @@ document.addEventListener("DOMContentLoaded", async () => { (elements.options.matchingMaxComparisons.value = config.matchingMaxComparisons.toString()); Object.entries(elements.options).forEach(([option, element]) => - element.addEventListener("change", () => { + element.addEventListener('change', () => { config = { ...config, [option]: element.value }; drawAndUpdateUrl(elements.url.input.value, diffString, config, elements); - }) + }), ); Object.entries(elements.checkboxes).forEach(([option, checkbox]) => - checkbox.addEventListener("change", () => { + checkbox.addEventListener('change', () => { config = { ...config, [option]: checkbox.checked }; drawAndUpdateUrl(elements.url.input.value, diffString, config, elements); - }) + }), ); - elements.url.button.addEventListener("click", async e => { + elements.url.button.addEventListener('click', async e => { e.preventDefault(); const newDiffUrl = elements.url.input.value; const newRequest = prepareRequest(newDiffUrl); diff --git a/website/templates/pages/index/index.css b/website/templates/pages/index/index.css index a8c6464..330d2d6 100644 --- a/website/templates/pages/index/index.css +++ b/website/templates/pages/index/index.css @@ -1,93 +1,97 @@ .screenshot { - display: block; - overflow: hidden; - } - - .screenshot > img { - width: 100% - } - + display: block; + overflow: hidden; +} + +.screenshot > img { + width: 100%; +} + +.screenshots-fan { + margin-top: 50px; +} + +.screenshots-fan .screenshot { + position: relative; + width: auto; + display: inline-block; + text-align: center; +} + +.screenshots-fan .screenshot:last-child, +.screenshots-fan .screenshot:first-child { + z-index: 2; +} + +.screenshots-fan .screenshot { + z-index: 3; +} + +@media (min-width: 768px) { .screenshots-fan { - margin-top: 50px - } - - .screenshots-fan .screenshot { position: relative; - width: auto; - display: inline-block; - text-align: center; - } - - .screenshots-fan .screenshot:last-child, .screenshots-fan .screenshot:first-child { - z-index: 2 - } - - .screenshots-fan .screenshot { - z-index: 3 - } - - @media (min-width: 768px) { - .screenshots-fan { - position: relative; - overflow: hidden; - margin-top: 60px; - height: 200px - } - - .screenshots-fan .screenshot { - height: auto; - top: 10px; - width: 350px - } - - .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { - width: 250px; - position: absolute; - top: 65px - } - - .screenshots-fan .screenshot:first-child { - left: 10px - } - - .screenshots-fan .screenshot:last-child { - left: auto; - right: 10px - } - } - - @media (min-width: 992px) { - .screenshots-fan { - margin-top: 60px; - height: 240px - } - - .screenshots-fan .screenshot { - width: 400px - } - - .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { - width: 300px - } - } - - @media (min-width: 1200px) { - .screenshots-fan { - margin-top: 80px; - height: 380px - } - - .screenshots-fan .screenshot { - width: 550px - } - - .screenshots-fan .screenshot:first-child, .screenshots-fan .screenshot:last-child { - width: 450px - } + overflow: hidden; + margin-top: 60px; + height: 200px; } + .screenshots-fan .screenshot { + height: auto; + top: 10px; + width: 350px; + } + + .screenshots-fan .screenshot:first-child, + .screenshots-fan .screenshot:last-child { + width: 250px; + position: absolute; + top: 65px; + } + + .screenshots-fan .screenshot:first-child { + left: 10px; + } + + .screenshots-fan .screenshot:last-child { + left: auto; + right: 10px; + } +} + +@media (min-width: 992px) { + .screenshots-fan { + margin-top: 60px; + height: 240px; + } + + .screenshots-fan .screenshot { + width: 400px; + } + + .screenshots-fan .screenshot:first-child, + .screenshots-fan .screenshot:last-child { + width: 300px; + } +} + +@media (min-width: 1200px) { + .screenshots-fan { + margin-top: 80px; + height: 380px; + } + + .screenshots-fan .screenshot { + width: 550px; + } + + .screenshots-fan .screenshot:first-child, + .screenshots-fan .screenshot:last-child { + width: 450px; + } +} + .img-snapshot1 { - background-image: url("./images/snapshot-1.png"); + background-image: url('./images/snapshot-1.png'); background-repeat: no-repeat; /* height: 50px; width: 50px; */ @@ -95,7 +99,7 @@ } .img-snapshot2 { - background-image: url("./images/snapshot-2.png"); + background-image: url('./images/snapshot-2.png'); background-repeat: no-repeat; /* height: 50px; width: 50px; */ @@ -103,7 +107,7 @@ } .img-snapshot3 { - background-image: url("./images/snapshot-3.png"); + background-image: url('./images/snapshot-3.png'); background-repeat: no-repeat; /* height: 50px; width: 50px; */ diff --git a/website/templates/pages/index/index.ts b/website/templates/pages/index/index.ts index fbdc699..f33705b 100644 --- a/website/templates/pages/index/index.ts +++ b/website/templates/pages/index/index.ts @@ -1,8 +1,8 @@ -import Clipboard from "clipboard"; +import Clipboard from 'clipboard'; -import "../../../main.ts"; -import "../../../main.css"; -import "./index.css"; +import '../../../main.ts'; +import '../../../main.css'; +import './index.css'; // eslint-disable-next-line no-new -new Clipboard(document.getElementsByClassName("btn-clipboard")[0]); +new Clipboard(document.getElementsByClassName('btn-clipboard')[0]); diff --git a/yarn.lock b/yarn.lock index 4b59d06..0ff7634 100644 --- a/yarn.lock +++ b/yarn.lock @@ -143,11 +143,6 @@ resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== -"@csstools/normalize.css@^10.1.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-10.1.0.tgz#f0950bba18819512d42f7197e56c518aa491cf18" - integrity sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg== - "@jest/console@^24.7.1", "@jest/console@^24.9.0": version "24.9.0" resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" @@ -330,6 +325,13 @@ "@nodelib/fs.scandir" "2.1.3" fastq "^1.6.0" +"@samverschueren/stream-to-observable@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" + integrity sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg== + dependencies: + any-observable "^0.3.0" + "@sindresorhus/is@^0.7.0": version "0.7.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" @@ -340,14 +342,6 @@ resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== -"@types/autoprefixer@9.6.1": - version "9.6.1" - resolved "https://registry.yarnpkg.com/@types/autoprefixer/-/autoprefixer-9.6.1.tgz#8bfaf43d18f5cd59a269b7a2364e690cadcdf210" - integrity sha512-9aofAxm/OWxzu/Fq7lU/m2rX03f9Sr1OXF/3kEp6FNFYRFLgFcIUjxhNGgWqc5KMpXbkqxlJmc7wfab7jFj2dw== - dependencies: - "@types/browserslist" "*" - postcss "7.x.x" - "@types/babel__core@^7.1.0": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30" @@ -381,11 +375,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/browserslist@*": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@types/browserslist/-/browserslist-4.4.0.tgz#e2a5f7f8c7e97afb39f50812a77e5230d3ca2353" - integrity sha512-hrIjWSu7Hh96/rKlpChe58qHEwIZ0+F5Zf4QNdvSVP5LUXbaJM04g9tBjo702VTNqPZr5znEJeqNR3nAV3vJPg== - "@types/clean-css@*": version "4.2.1" resolved "https://registry.yarnpkg.com/@types/clean-css/-/clean-css-4.2.1.tgz#cb0134241ec5e6ede1b5344bc829668fd9871a8d" @@ -479,22 +468,22 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" -"@types/jest@24.0.24": - version "24.0.24" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.24.tgz#0f2f523dc77cc1bc6bef34eaf287ede887a73f05" - integrity sha512-vgaG968EDPSJPMunEDdZvZgvxYSmeH8wKqBlHSkBt1pV2XlLEVDzsj1ZhLuI4iG4Pv841tES61txSBF0obh4CQ== +"@types/jest@24.0.25": + version "24.0.25" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.25.tgz#2aba377824ce040114aa906ad2cac2c85351360f" + integrity sha512-hnP1WpjN4KbGEK4dLayul6lgtys6FPz0UfxMeMQCv0M+sTnzN3ConfiO72jHgLxl119guHgI8gLqDOrRLsyp2g== dependencies: jest-diff "^24.3.0" "@types/json-schema@^7.0.3": - version "7.0.3" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.3.tgz#bdfd69d61e464dcc81b25159c270d75a73c1a636" - integrity sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A== + version "7.0.4" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" + integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== -"@types/mini-css-extract-plugin@0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz#6a5d3459d40cb51f14059e9aa410c9e970656103" - integrity sha512-L7OKmXudo048RMw/NeLjJMNRAbyXG76b3uGZ49OKe03imYEplx0JzcM0goVNc7X1IeESf2Bk9RP+tS1U3OSmVg== +"@types/mini-css-extract-plugin@0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@types/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#ab11dde0662e2e7c711acee554a8983c2e036c8b" + integrity sha512-y+/Z/FtQ0h0Ps9PYbYeBd9fVl1z4215gpvGcYfl20+jMWBngEKDNzQ2an2kz+cLL47SS6Y2f6Z4axdSoyNgNAw== dependencies: "@types/webpack" "*" @@ -510,16 +499,26 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@12.12.21": - version "12.12.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f" - integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== +"@types/node@*": + version "13.1.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.2.tgz#fe94285bf5e0782e1a9e5a8c482b1c34465fa385" + integrity sha512-B8emQA1qeKerqd1dmIsQYnXi+mmAzTB7flExjmy5X1aVAKFNNNDubkavwR13kR6JnpeLp3aLoJhwn9trWPAyFQ== + +"@types/node@13.1.1": + version "13.1.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.1.1.tgz#6d11a8c2d58405b3db9388ab740106cbfa64c3c9" + integrity sha512-hx6zWtudh3Arsbl3cXay+JnkvVgCKzCWKv42C9J01N2T2np4h8w5X8u6Tpz5mj38kE3M9FM0Pazx8vKFFMnjLQ== "@types/nopt@3.0.29": version "3.0.29" resolved "https://registry.yarnpkg.com/@types/nopt/-/nopt-3.0.29.tgz#f19df3db4c97ee1459a2740028320a71d70964ce" integrity sha1-8Z3z20yX7hRZonQAKDIKcdcJZM4= +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + "@types/q@^1.5.1": version "1.5.2" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" @@ -561,7 +560,19 @@ "@types/source-list-map" "*" source-map "^0.6.1" -"@types/webpack@*", "@types/webpack@4.41.0": +"@types/webpack@*": + version "4.41.1" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.1.tgz#571f0e137ce698710dd2637f7d222811eb83e274" + integrity sha512-n9fP8UrMxOi1wiM3oM+vMZHMJJ7WoQohqd63C20cmKOFkNEy9Q8hyZyDR6PWdvSYt3V3A7cwDq/kWxHlRYYZEg== + dependencies: + "@types/anymatch" "*" + "@types/node" "*" + "@types/tapable" "*" + "@types/uglify-js" "*" + "@types/webpack-sources" "*" + source-map "^0.6.0" + +"@types/webpack@4.41.0": version "4.41.0" resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.0.tgz#b813a044d8b0dec7dfcd7622fdbe327bde06eb9a" integrity sha512-tWkdf9nO0zFgAY/EumUKwrDUhraHKDqCPhwfFR/R8l0qnPdgb9le0Gzhvb7uzVpouuDGBgiE//ZdY+5jcZy2TA== @@ -579,46 +590,68 @@ integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg== "@types/yargs@^13.0.0": - version "13.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.3.tgz#76482af3981d4412d65371a318f992d33464a380" - integrity sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ== + version "13.0.4" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.4.tgz#53d231cebe1a540e7e13727fc1f0d13ad4a9ba3b" + integrity sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A== dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@2.12.0": - version "2.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.12.0.tgz#0da7cbca7b24f4c6919e9eb31c704bfb126f90ad" - integrity sha512-1t4r9rpLuEwl3hgt90jY18wJHSyb0E3orVL3DaqwmpiSDHmHiSspVsvsFF78BJ/3NNG3qmeso836jpuBWYziAA== +"@typescript-eslint/eslint-plugin@2.13.0": + version "2.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.13.0.tgz#57e933fe16a2fc66dbac059af0d6d85d921d748e" + integrity sha512-QoiANo0MMGNa8ej/yX3BrW5dZj5d8HYcKiM2fyYUlezECqn8Xc7T/e4EUdiGinn8jhBrn+9X47E9TWaaup3u1g== dependencies: - "@typescript-eslint/experimental-utils" "2.12.0" + "@typescript-eslint/experimental-utils" "2.13.0" eslint-utils "^1.4.3" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@2.12.0", "@typescript-eslint/experimental-utils@^2.5.0": - version "2.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.12.0.tgz#e0a76ffb6293e058748408a191921e453c31d40d" - integrity sha512-jv4gYpw5N5BrWF3ntROvCuLe1IjRenLy5+U57J24NbPGwZFAjhnM45qpq0nDH1y/AZMb3Br25YiNVwyPbz6RkA== +"@typescript-eslint/experimental-utils@2.13.0": + version "2.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.13.0.tgz#958614faa6f77599ee2b241740e0ea402482533d" + integrity sha512-+Hss3clwa6aNiC8ZjA45wEm4FutDV5HsVXPl/rDug1THq6gEtOYRGLqS3JlTk7mSnL5TbJz0LpEbzbPnKvY6sw== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.12.0" + "@typescript-eslint/typescript-estree" "2.13.0" eslint-scope "^5.0.0" -"@typescript-eslint/parser@2.12.0": - version "2.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.12.0.tgz#393f1604943a4ca570bb1a45bc8834e9b9158884" - integrity sha512-lPdkwpdzxEfjI8TyTzZqPatkrswLSVu4bqUgnB03fHSOwpC7KSerPgJRgIAf11UGNf7HKjJV6oaPZI4AghLU6g== +"@typescript-eslint/experimental-utils@^2.5.0": + version "2.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.14.0.tgz#e9179fa3c44e00b3106b85d7b69342901fb43e3b" + integrity sha512-KcyKS7G6IWnIgl3ZpyxyBCxhkBPV+0a5Jjy2g5HxlrbG2ZLQNFeneIBVXdaBCYOVjvGmGGFKom1kgiAY75SDeQ== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.14.0" + eslint-scope "^5.0.0" + +"@typescript-eslint/parser@2.13.0": + version "2.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.13.0.tgz#ea1ab394cf9ca17467e3da7f96eca9309f57c326" + integrity sha512-vbDeLr5QRJ1K7x5iRK8J9wuGwR9OVyd1zDAY9XFAQvAosHVjSVbDgkm328ayE6hx2QWVGhwvGaEhedcqAbfQcA== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.12.0" - "@typescript-eslint/typescript-estree" "2.12.0" + "@typescript-eslint/experimental-utils" "2.13.0" + "@typescript-eslint/typescript-estree" "2.13.0" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/typescript-estree@2.12.0": - version "2.12.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.12.0.tgz#bd9e547ccffd17dfab0c3ab0947c80c8e2eb914c" - integrity sha512-rGehVfjHEn8Frh9UW02ZZIfJs6SIIxIu/K1bbci8rFfDE/1lQ8krIJy5OXOV3DVnNdDPtoiPOdEANkLMrwXbiQ== +"@typescript-eslint/typescript-estree@2.13.0": + version "2.13.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.13.0.tgz#a2e746867da772c857c13853219fced10d2566bc" + integrity sha512-t21Mg5cc8T3ADEUGwDisHLIubgXKjuNRbkpzDMLb7/JMmgCe/gHM9FaaujokLey+gwTuLF5ndSQ7/EfQqrQx4g== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash.unescape "4.0.1" + semver "^6.3.0" + tsutils "^3.17.1" + +"@typescript-eslint/typescript-estree@2.14.0": + version "2.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.14.0.tgz#c67698acdc14547f095eeefe908958d93e1a648d" + integrity sha512-pnLpUcMNG7GfFFfNQbEX6f1aPa5fMnH2G9By+A1yovYI4VIOK2DzkaRuUlIkbagpAcrxQHLqovI1YWqEcXyRnA== dependencies: debug "^4.1.1" eslint-visitor-keys "^1.1.0" @@ -835,6 +868,14 @@ acorn@^7.1.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== +aggregate-error@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv-errors@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" @@ -914,6 +955,11 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +any-observable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" + integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -922,12 +968,7 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -apollojs@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/apollojs/-/apollojs-1.3.0.tgz#5f7b00304d9740e2a7be5b52c7c0807d51f9255e" - integrity sha1-X3sAME2XQOKnvltSx8CAfVH5JV4= - -aproba@^1.0.3, aproba@^1.1.1: +aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== @@ -944,14 +985,6 @@ archive-type@^4.0.0: dependencies: file-type "^4.2.0" -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - arg@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.2.tgz#e70c90579e02c63d80e3ad4e31d8bfdb8bd50064" @@ -1104,7 +1137,7 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== @@ -1443,7 +1476,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.6.2, browserslist@^4.6.4, browserslist@^4.8.0: +browserslist@^4.0.0, browserslist@^4.6.4, browserslist@^4.8.0: version "4.8.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.2.tgz#b45720ad5fbc8713b7253c20766f701c9a694289" integrity sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA== @@ -1656,9 +1689,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001012, caniuse-lite@^1.0.30001015: - version "1.0.30001016" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001016.tgz#16ea48d7d6e8caf3cad3295c2d746fe38c4e7f66" - integrity sha512-yYQ2QfotceRiH4U+h1Us86WJXtVHDmy3nEKIdYPsZCYnOV5/tMgGbmoIlrMzmh2VXlproqYtVaKeGDBkMZifFA== + version "1.0.30001017" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001017.tgz#d3ad6ec18148b9bd991829958d9d7e562bb78cd6" + integrity sha512-EDnZyOJ6eYh6lHmCvCdHAFbfV4KJ9lSdfv4h/ppEhrU/Yudkl7jujwMZ1we6RX7DXqBfT04pVMQ4J+1wcTlsKA== capture-exit@^2.0.0: version "2.0.0" @@ -1691,7 +1724,7 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4. escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^1.0.0: +chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= @@ -1768,6 +1801,18 @@ clean-css@4.2.x: dependencies: source-map "~0.6.0" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^2.0.0, cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -1775,6 +1820,14 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + integrity sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ= + dependencies: + slice-ansi "0.0.4" + string-width "^1.0.1" + cli-width@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" @@ -1986,11 +2039,6 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - console-stream@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/console-stream/-/console-stream-0.1.1.tgz#a095fe07b20465955f2fafd28b5d72bccd949d44" @@ -2075,7 +2123,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^5.0.0: +cosmiconfig@^5.0.0, cosmiconfig@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== @@ -2136,6 +2184,15 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" + integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -2393,6 +2450,11 @@ data-urls@^1.0.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" +date-fns@^1.27.2: + version "1.30.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" + integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== + debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -2407,7 +2469,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@^3.0.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@^3.0.0, debug@^3.1.1, debug@^3.2.5: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -2491,6 +2553,11 @@ decompress@^4.0.0, decompress@^4.2.0: pify "^2.3.0" strip-dirs "^2.0.0" +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= + deep-equal@^1.0.1: version "1.1.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" @@ -2503,11 +2570,6 @@ deep-equal@^1.0.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -2563,6 +2625,20 @@ del@^4.1.1: pify "^4.0.1" rimraf "^2.6.3" +del@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/del/-/del-5.1.0.tgz#d9487c94e367410e6eff2925ee58c0c84a75b3a7" + integrity sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA== + dependencies: + globby "^10.0.1" + graceful-fs "^4.2.2" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.1" + p-map "^3.0.0" + rimraf "^3.0.0" + slash "^3.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -2573,11 +2649,6 @@ delegate@^3.1.2: resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -2606,11 +2677,6 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" @@ -2829,6 +2895,11 @@ electron-to-chromium@^1.3.322: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8" integrity sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA== +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" + integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= + elliptic@^6.0.0: version "6.5.2" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" @@ -2959,18 +3030,13 @@ escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz#9a876952e12df2b284adbd3440994bf1f39dfbb9" - integrity sha512-FamQVKM3jjUVwhG4hEMnbtsq7xOIDm+SY5iBPfR8gKsJoAB2IQnNF+bk1+8Fy44Nq7PPJaLvkRxILYdJWoguKQ== +eslint-config-prettier@6.9.0: + version "6.9.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.9.0.tgz#430d24822e82f7deb1e22a435bfa3999fae4ad64" + integrity sha512-k4E14HBtcLv0uqThaI6I/n1LEqROp8XaPu6SO9Z32u5NlGRC07Enu1Bh2KEFw4FNHbekH8yzbIU9kUGxbiGmCA== dependencies: get-stdin "^6.0.0" -eslint-config-standard@14.1.0: - version "14.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz#b23da2b76fe5a2eba668374f246454e7058f15d4" - integrity sha512-EF6XkrrGVbvv8hL/kYa/m6vnvmUT+K82pJJc4JJVMM6+Qgqh0pnwprSxdduDLB9p/7bIxD+YV5O0wfb8lmcPbA== - eslint-import-resolver-node@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" @@ -2987,12 +3053,12 @@ eslint-module-utils@^2.4.1: debug "^2.6.9" pkg-dir "^2.0.0" -eslint-plugin-es@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-2.0.0.tgz#0f5f5da5f18aa21989feebe8a73eadefb3432976" - integrity sha512-f6fceVtg27BR02EYnBhgWLFQfK6bN4Ll0nQFrBHOlCsAyxeZkn0NHns5O0YZOPrV1B3ramd6cgFwaoFLcSkwEQ== +eslint-plugin-es@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz#98cb1bc8ab0aa807977855e11ad9d1c9422d014b" + integrity sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng== dependencies: - eslint-utils "^1.4.2" + eslint-utils "^2.0.0" regexpp "^3.0.0" eslint-plugin-import@2.19.1: @@ -3013,41 +3079,49 @@ eslint-plugin-import@2.19.1: read-pkg-up "^2.0.0" resolve "^1.12.0" -eslint-plugin-jest@23.1.1: - version "23.1.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.1.1.tgz#1220ab53d5a4bf5c3c4cd07c0dabc6199d4064dd" - integrity sha512-2oPxHKNh4j1zmJ6GaCBuGcb8FVZU7YjFUOJzGOPnl9ic7VA/MGAskArLJiRIlnFUmi1EUxY+UiATAy8dv8s5JA== +eslint-plugin-jest@23.2.0: + version "23.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.2.0.tgz#72d9ac0421b9b6ef774bcf4783329c016ed7cd6a" + integrity sha512-/jbCUW+g0jejXAvsytgcNhii6uEgolt0RO2e4+mhmXybfkcram5V3XIyrHCnUsb0vCmDKgHhJ1lYSm7F3VCEDA== dependencies: "@typescript-eslint/experimental-utils" "^2.5.0" -eslint-plugin-node@10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-10.0.0.tgz#fd1adbc7a300cf7eb6ac55cf4b0b6fc6e577f5a6" - integrity sha512-1CSyM/QCjs6PXaT18+zuAXsjXGIGo5Rw630rSKwokSs2jrYURQc4R5JZpoanNCqwNmepg+0eZ9L7YiRUJb8jiQ== +eslint-plugin-json@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-json/-/eslint-plugin-json-2.0.1.tgz#825ba21fed9522a7080044f0692ffffffbc237e3" + integrity sha512-IxKZIlMyBn0tvxlBj2viW0N/UBuoey1oYpV+SNVuNFmy4xsNuwgeoOjzEeFDnVXL0FpIo7UbQSeZ+lfh2D/nLQ== dependencies: - eslint-plugin-es "^2.0.0" - eslint-utils "^1.4.2" + lodash "^4.17.15" + vscode-json-languageservice "^3.3.5" + +eslint-plugin-node@11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.0.0.tgz#365944bb0804c5d1d501182a9bc41a0ffefed726" + integrity sha512-chUs/NVID+sknFiJzxoN9lM7uKSOEta8GC8365hw1nDfwIPIjjpRSwwPvQanWv8dt/pDe9EV4anmVSwdiSndNg== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" ignore "^5.1.1" minimatch "^3.0.4" resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-prettier@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" - integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== +eslint-plugin-optimize-regex@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/eslint-plugin-optimize-regex/-/eslint-plugin-optimize-regex-1.1.7.tgz#9368fe1243efbe034f3cc24acfd5e4b7ddb8eb40" + integrity sha512-YiMp9uerCHqG+EhfQhCNNDyjWkaya2L8ggg0+ou5f1oVu51IK+ziE1VlzaILFVTrhU1llAQw+vNn7cOd73VtwQ== dependencies: - prettier-linter-helpers "^1.0.0" + regexp-tree "0.1.11" eslint-plugin-promise@4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== -eslint-plugin-standard@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" - integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== +eslint-plugin-sonarjs@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.5.0.tgz#ce17b2daba65a874c2862213a9e38e8986ad7d7d" + integrity sha512-XW5MnzlRjhXpIdbULC/qAdJYHWw3rRLws/DyawdlPU/IdVr9AmRK1r2LaCvabwKOAW2XYYSo3kDX58E4MrB7PQ== eslint-scope@^4.0.3: version "4.0.3" @@ -3065,13 +3139,20 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^1.4.2, eslint-utils@^1.4.3: +eslint-utils@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" + integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== + dependencies: + eslint-visitor-keys "^1.1.0" + eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" @@ -3248,6 +3329,21 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-2.1.0.tgz#e5d3ecd837d2a60ec50f3da78fd39767747bbe99" + integrity sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^3.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + executable@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" @@ -3401,11 +3497,6 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - fast-glob@^2.2.6: version "2.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" @@ -3429,14 +3520,6 @@ fast-glob@^3.0.3: merge2 "^1.3.0" micromatch "^4.0.2" -fast-html-parser@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fast-html-parser/-/fast-html-parser-1.0.1.tgz#4ecc9683b8bb79afe11a50807b7853e79256cea2" - integrity sha1-TsyWg7i7ea/hGlCAe3hT55JWzqI= - dependencies: - apollojs "^1.3.0" - entities "^1.1.1" - fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -3492,7 +3575,7 @@ figgy-pudding@^3.5.1: resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== -figures@^1.3.5: +figures@^1.3.5, figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= @@ -3500,6 +3583,13 @@ figures@^1.3.5: escape-string-regexp "^1.0.5" object-assign "^4.1.0" +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + figures@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" @@ -3637,6 +3727,14 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-versions@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" @@ -3746,13 +3844,6 @@ fs-extra@^7.0.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -3786,20 +3877,6 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" @@ -3810,6 +3887,11 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-own-enumerable-property-symbols@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== + get-proxy@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" @@ -3827,6 +3909,11 @@ get-stdin@^6.0.0: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== +get-stdin@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" + integrity sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ== + get-stream@3.0.0, get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -3847,6 +3934,13 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" +get-stream@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -3961,7 +4055,7 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -globby@^10.0.0: +globby@^10.0.0, globby@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== @@ -4150,11 +4244,6 @@ has-to-string-tag-x@^1.2.0: dependencies: has-symbol-support-x "^1.4.1" -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -4425,7 +4514,24 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: +husky@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/husky/-/husky-3.1.0.tgz#5faad520ab860582ed94f0c1a77f0f04c90b57c0" + integrity sha512-FJkPoHHB+6s4a+jwPqBudBDvYZsoQW5/HBuMSehC8qDiCe50kpcxeqFoDSlow+9I6wg47YxBoT3WxaURlrDIIQ== + dependencies: + chalk "^2.4.2" + ci-info "^2.0.0" + cosmiconfig "^5.2.1" + execa "^1.0.0" + get-stdin "^7.0.0" + opencollective-postinstall "^2.0.2" + pkg-dir "^4.2.0" + please-upgrade-node "^3.2.0" + read-pkg "^5.2.0" + run-node "^1.0.0" + slash "^3.0.0" + +iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4449,13 +4555,6 @@ iferr@^0.1.5: resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= -ignore-walk@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" - integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== - dependencies: - minimatch "^3.0.4" - ignore@^3.3.5: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" @@ -4610,6 +4709,16 @@ indent-string@^2.1.0: dependencies: repeating "^2.0.0" +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + indexes-of@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" @@ -4643,7 +4752,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: +ini@^1.3.4, ini@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -4776,6 +4885,14 @@ is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-ci-cli@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci-cli/-/is-ci-cli-2.0.0.tgz#606dd5051c636ac80e1deb4c1c30aa5294220159" + integrity sha512-pgdXwbBaRfyG3XJ/+AYbgCb5WE10TZwj4pvoSYI1YrmGDslcS0lhvqvAKmZrSq2248/jGoZ2g9yC63APlBy1uQ== + dependencies: + cross-spawn "^7.0.0" + is-ci "^2.0.0" + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -4933,7 +5050,7 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.0: +is-obj@^1.0.0, is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= @@ -4943,7 +5060,14 @@ is-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= -is-path-cwd@^2.0.0: +is-observable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" + integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA== + dependencies: + symbol-observable "^1.1.0" + +is-path-cwd@^2.0.0, is-path-cwd@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== @@ -4962,6 +5086,11 @@ is-path-inside@^2.1.0: dependencies: path-is-inside "^1.0.2" +is-path-inside@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" + integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== + is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -4991,6 +5120,11 @@ is-regex@^1.0.4, is-regex@^1.0.5: dependencies: has "^1.0.3" +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= + is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" @@ -5617,6 +5751,11 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" +jsonc-parser@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.0.tgz#f206f87f9d49d644b7502052c04e82dd6392e9ef" + integrity sha512-4fLQxW1j/5fWj6p78vAlAafoCKtuBm6ghv+Ij5W2DrDx0qE+ZdEl2c6Ko1mgJNF5ftX1iEWQQ4Ap7+3GlhjkOA== + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -5710,6 +5849,75 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + +lint-staged@9.5.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-9.5.0.tgz#290ec605252af646d9b74d73a0fa118362b05a33" + integrity sha512-nawMob9cb/G1J98nb8v3VC/E8rcX1rryUYXVZ69aT9kde6YWX+uvNOEHY5yf2gcWcTJGiD0kqXmCnS3oD75GIA== + dependencies: + chalk "^2.4.2" + commander "^2.20.0" + cosmiconfig "^5.2.1" + debug "^4.1.1" + dedent "^0.7.0" + del "^5.0.0" + execa "^2.0.3" + listr "^0.14.3" + log-symbols "^3.0.0" + micromatch "^4.0.2" + normalize-path "^3.0.0" + please-upgrade-node "^3.1.1" + string-argv "^0.3.0" + stringify-object "^3.3.0" + +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4= + +listr-update-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" + integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA== + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^2.3.0" + strip-ansi "^3.0.1" + +listr-verbose-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" + integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== + dependencies: + chalk "^2.4.1" + cli-cursor "^2.1.0" + date-fns "^1.27.2" + figures "^2.0.0" + +listr@^0.14.3: + version "0.14.3" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" + integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== + dependencies: + "@samverschueren/stream-to-observable" "^0.3.0" + is-observable "^1.1.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.5.0" + listr-verbose-renderer "^0.5.0" + p-map "^2.0.0" + rxjs "^6.3.3" + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -5790,6 +5998,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -5840,6 +6055,13 @@ log-driver@^1.x: resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg= + dependencies: + chalk "^1.0.0" + log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" @@ -5847,6 +6069,22 @@ log-symbols@^2.2.0: dependencies: chalk "^2.0.1" +log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + +log-update@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" + integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg= + dependencies: + ansi-escapes "^3.0.0" + cli-cursor "^2.0.0" + wrap-ansi "^3.0.1" + logalot@^2.0.0, logalot@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/logalot/-/logalot-2.1.0.tgz#5f8e8c90d304edf12530951a5554abb8c5e3f552" @@ -6120,6 +6358,11 @@ mime@^2.4.4: resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -6172,21 +6415,6 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" @@ -6216,7 +6444,7 @@ mkdirp@0.3.0: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= -mkdirp@0.5.1, mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@0.x, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -6321,15 +6549,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -6407,26 +6626,10 @@ node-notifier@^5.4.2: shellwords "^0.1.1" which "^1.3.0" -node-pre-gyp@*: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4.4.2" - node-releases@^1.1.42: - version "1.1.43" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.43.tgz#2c6ca237f88ce11d49631f11190bb01f8d0549f2" - integrity sha512-Rmfnj52WNhvr83MvuAWHEqXVoZXCcDQssSOffU4n4XOL9sPrP61mSZ88g25NqmABDvH7PiAlFCzoSCSdzA293w== + version "1.1.44" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.44.tgz#cd66438a6eb875e3eb012b6a12e48d9f4326ffd7" + integrity sha512-NwbdvJyR7nrcGrXvKAvzc5raj/NkoJudkarh2yIpJ4t0NH4aqjUDz/486P+ynIW5eokKOfzGNRdYoLfBlomruw== dependencies: semver "^6.3.0" @@ -6437,7 +6640,7 @@ nopt@1.0.10: dependencies: abbrev "1" -nopt@4.0.1, nopt@^4.0.1: +nopt@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= @@ -6445,7 +6648,7 @@ nopt@4.0.1, nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -6496,13 +6699,6 @@ normalize-url@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== -npm-bundled@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" - integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== - dependencies: - npm-normalize-package-bin "^1.0.1" - npm-conf@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" @@ -6511,19 +6707,6 @@ npm-conf@^1.1.0: config-chain "^1.1.11" pify "^3.0.0" -npm-normalize-package-bin@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" - integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== - -npm-packlist@^1.1.6: - version "1.4.7" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848" - integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -6531,15 +6714,12 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== +npm-run-path@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" + integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" + path-key "^3.0.0" nth-check@^1.0.2, nth-check@~1.0.1: version "1.0.2" @@ -6663,6 +6843,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + onetime@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" @@ -6670,6 +6857,11 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +opencollective-postinstall@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" + integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== + opn@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" @@ -6800,6 +6992,11 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= +p-finally@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== + p-is-promise@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" @@ -6817,10 +7014,10 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0, p-limit@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== +p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== dependencies: p-try "^2.0.0" @@ -6838,6 +7035,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-map-series@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" @@ -6850,6 +7054,13 @@ p-map@^2.0.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + p-pipe@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.0.0.tgz#ab1fb87c0b8dd79b3bb03a8a23680fc9d054e132" @@ -6946,6 +7157,16 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -6988,6 +7209,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -7003,6 +7229,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -7115,6 +7346,20 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +please-upgrade-node@^3.1.1, please-upgrade-node@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== + dependencies: + semver-compare "^1.0.0" + pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" @@ -7152,13 +7397,6 @@ postcss-attribute-case-insensitive@^4.0.1: postcss "^7.0.2" postcss-selector-parser "^5.0.0" -postcss-browser-comments@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postcss-browser-comments/-/postcss-browser-comments-3.0.0.tgz#1248d2d935fb72053c8e1f61a84a57292d9f65e9" - integrity sha512-qfVjLfq7HFd2e0HW4s1dvU8X080OZdG46fFbIBFjW7US7YPDcWfRvdElvwMJr2LI6hMmD+7LnH2HcmXTs+uOig== - dependencies: - postcss "^7" - postcss-calc@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" @@ -7601,17 +7839,6 @@ postcss-normalize-whitespace@^4.0.2: postcss "^7.0.0" postcss-value-parser "^3.0.0" -postcss-normalize@8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize/-/postcss-normalize-8.0.1.tgz#90e80a7763d7fdf2da6f2f0f82be832ce4f66776" - integrity sha512-rt9JMS/m9FHIRroDDBGSMsyW1c0fkvOJPy62ggxSHUldJO7B195TqFMqIf+lY5ezpDcYOV4j86aUp3/XbxzCCQ== - dependencies: - "@csstools/normalize.css" "^10.1.0" - browserslist "^4.6.2" - postcss "^7.0.17" - postcss-browser-comments "^3.0.0" - sanitize.css "^10.0.0" - postcss-ordered-values@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" @@ -7812,7 +8039,7 @@ postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: indexes-of "^1.0.1" uniq "^1.0.1" -postcss@7.x.x, postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.23, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7: +postcss@7.0.25: version "7.0.25" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.25.tgz#dd2a2a753d50b13bed7a2009b4a18ac14d9db21e" integrity sha512-NXXVvWq9icrm/TgQC0O6YVFi4StfJz46M1iNd/h6B26Nvh/HKI+q4YZtFN/EjcInZliEscO/WL10BXnc1E5nwg== @@ -7821,6 +8048,15 @@ postcss@7.x.x, postcss@^7, postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, post source-map "^0.6.1" supports-color "^6.1.0" +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.23, postcss@^7.0.5, postcss@^7.0.6, postcss@^7.0.7: + version "7.0.26" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587" + integrity sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -7836,13 +8072,6 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@1.19.1: version "1.19.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" @@ -7923,9 +8152,9 @@ pseudomap@^1.0.2: integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24, psl@^1.1.28: - version "1.6.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110" - integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA== + version "1.7.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" + integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== public-encrypt@^4.0.0: version "4.0.3" @@ -8056,16 +8285,6 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - react-is@^16.8.4: version "16.12.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" @@ -8129,7 +8348,17 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -8183,6 +8412,11 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp-tree@0.1.11: + version "0.1.11" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.11.tgz#c9c7f00fcf722e0a56c7390983a7a63dd6c272f3" + integrity sha512-7/l/DgapVVDzZobwMCCgMlqiqyLFJ0cduo/j+3BcDJIB+yJdsYCfKuI3l/04NV+H/rfNRdPIDbXNZHM9XvQatg== + regexp.prototype.flags@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" @@ -8365,6 +8599,14 @@ responselike@1.0.2: dependencies: lowercase-keys "^1.0.0" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -8405,13 +8647,20 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: +rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" +rimraf@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.0.tgz#614176d4b3010b75e5c390eb0ee96f6dc0cebb9b" + integrity sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -8432,6 +8681,11 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +run-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e" + integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A== + run-parallel@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" @@ -8444,10 +8698,10 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^6.5.3: - version "6.5.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" - integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== +rxjs@^6.3.3, rxjs@^6.5.3: + version "6.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" + integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== dependencies: tslib "^1.9.0" @@ -8488,11 +8742,6 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -sanitize.css@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/sanitize.css/-/sanitize.css-10.0.0.tgz#b5cb2547e96d8629a60947544665243b1dc3657a" - integrity sha512-vTxrZz4dX5W86M6oVWVdOVe72ZiPs41Oi7Z6Km4W5Turyz28mrXSJhhEBZoRtzJWIv3833WKVwLSDWWkEfupMg== - sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -8507,7 +8756,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.0: +schema-utils@^2.5.0, schema-utils@^2.6.0: version "2.6.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.1.tgz#eb78f0b945c7bcfa2082b3565e8db3548011dc4f" integrity sha512-0WXHDs1VDJyo+Zqs9TKLKyD/h7yDpHUhEFsM2CzkICFdoX1av+GBq/J2xRTFfsQO5kBfhZzANf2VcIm84jqDbg== @@ -8539,6 +8788,11 @@ selfsigned@^1.10.7: dependencies: node-forge "0.9.0" +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + semver-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" @@ -8608,7 +8862,7 @@ serve-static@1.14.1: parseurl "~1.3.3" send "0.17.1" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -8653,11 +8907,23 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + shellwords@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" @@ -8695,6 +8961,11 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= + slice-ansi@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" @@ -8781,11 +9052,11 @@ source-list-map@^2.0.0: integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" @@ -8971,6 +9242,11 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= +string-argv@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" + integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== + string-length@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" @@ -8988,7 +9264,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: +string-width@^2.0.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -9044,6 +9320,15 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +stringify-object@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== + dependencies: + get-own-enumerable-property-symbols "^3.0.0" + is-obj "^1.0.1" + is-regexp "^1.0.0" + strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" @@ -9096,6 +9381,11 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" @@ -9108,11 +9398,6 @@ strip-json-comments@^3.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - strip-outer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" @@ -9120,14 +9405,6 @@ strip-outer@^1.0.0: dependencies: escape-string-regexp "^1.0.2" -style-loader@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.1.1.tgz#8290d915dffe820916790cdcab5aa58c38ab605c" - integrity sha512-oIVF12trRq0od4Yojg7q0K3Lq/O6Ix/AYgVosykrVg+kWxxxUyk8KhKCCmekyGSUiVK1xxlAQymLWWdh6S9lOg== - dependencies: - loader-utils "^1.2.3" - schema-utils "^2.0.1" - stylehacks@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" @@ -9182,6 +9459,11 @@ svgo@^1.0.0, svgo@^1.0.5: unquote "~1.1.1" util.promisify "~1.0.0" +symbol-observable@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== + symbol-tree@^3.2.2: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -9215,19 +9497,6 @@ tar-stream@^1.5.2: to-buffer "^1.1.1" xtend "^4.0.0" -tar@^4.4.2: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - temp-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" @@ -9515,6 +9784,11 @@ type-fest@^0.5.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -9547,9 +9821,9 @@ uglify-js@3.4.x: source-map "~0.6.1" uglify-js@^3.1.4: - version "3.7.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9" - integrity sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA== + version "3.7.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a" + integrity sha512-7tINm46/3puUA4hCkKYo4Xdts+JDaVC9ZPRcG8Xw9R4nhO/gZgUM3TENq8IF4Vatk8qCig4MzP/c8G4u2BkVQg== dependencies: commander "~2.20.3" source-map "~0.6.1" @@ -9774,6 +10048,37 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +vscode-json-languageservice@^3.3.5: + version "3.4.11" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.4.11.tgz#7c0632bccc4b2b955f99f99f43d96d3eece1de42" + integrity sha512-26Qv1SFp6x3XmCqU1BRceRsSKRO3xkQa6/K8ziSRt52/LQPiw5ipSxlGVSlzIoi5LCmQVEqUajhiVEMNlFXhNw== + dependencies: + jsonc-parser "^2.2.0" + vscode-languageserver-textdocument "^1.0.0-next.5" + vscode-languageserver-types "^3.15.0-next.9" + vscode-nls "^4.1.1" + vscode-uri "^2.1.1" + +vscode-languageserver-textdocument@^1.0.0-next.5: + version "1.0.0-next.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.0-next.5.tgz#dbb7a45dd973a19261a7c57ab9a439c40f3799ee" + integrity sha512-1jp/zAidN/bF/sqPimhBX1orH5G4rzRw63k75TesukJDuxm8yW79ECStWbDSy41BHGOwSGN4M69QFvhancSr5A== + +vscode-languageserver-types@^3.15.0-next.9: + version "3.15.0-next.9" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.9.tgz#957a9d1d5998a02edf62298fb7e37d9efcc6c157" + integrity sha512-Rl/8qJ6932nrHCdPn+9y0x08uLVQaSLRG+U4JzhyKpWU4eJbVaDRoAcz1Llj7CErJGbPr6kdBvShPy5fRfR+Uw== + +vscode-nls@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-4.1.1.tgz#f9916b64e4947b20322defb1e676a495861f133c" + integrity sha512-4R+2UoUUU/LdnMnFjePxfLqNhBS8lrAFyX7pjb2ud/lqDkrUavFUTcG7wR0HBZFakae0Q6KLBFjMS6W93F403A== + +vscode-uri@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.1.tgz#5aa1803391b6ebdd17d047f51365cf62c38f6e90" + integrity sha512-eY9jmGoEnVf8VE8xr5znSah7Qt1P/xsCdErz+g8HYZtJ7bZqKH5E3d+6oVNm1AC/c6IHUDokbmVXKOi4qPAC9A== + w3c-hr-time@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" @@ -9892,10 +10197,10 @@ webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1: source-list-map "^2.0.0" source-map "~0.6.1" -webpack@4.41.4: - version "4.41.4" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.4.tgz#4bec4125224bdf50efa8be6226c19047599cd034" - integrity sha512-Lc+2uB6NjpCWsHI3trkoISOI64h9QYIXenbEWj3bn3oyjfB1lEBXjWAfAyY2sM0rZn41oD5V91OLwKRwS6Wp8Q== +webpack@4.41.5: + version "4.41.5" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.5.tgz#3210f1886bce5310e62bb97204d18c263341b77c" + integrity sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" @@ -9982,12 +10287,12 @@ which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: - string-width "^1.0.2 || 2" + isexe "^2.0.0" word-wrap@~1.2.3: version "1.2.3" @@ -10014,6 +10319,14 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" + integrity sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo= + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" @@ -10091,7 +10404,7 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
- 1.1.9: Fix around ubuntu\'s inability to cache promises. [#877](https://github.com/FredrikNoren/ungit/pull/878)\n' + + ' - 1.1.8:\n' + + '@@ -11,7 +10,7 @@ $a="<table><tr><td>- 1.1.9: Fix around ubuntu's inability to cache promises. [#8\n' + + ' - 1.1.7:\n' + + ' - Fix diff flickering issue and optimization [#865](https://github.com/FredrikNoren/ungit/pull/865)\n' + + ' - Fix credential dialog issue [#864](https://github.com/FredrikNoren/ungit/pull/864)\n' + + '- - Fix HEAD branch order when redraw [#858](https://github.com/FredrikNoren/ungit/issues/858)\n' + + '+4 - Fix HEAD branch order when redraw [#858](https://github.com/FredrikNoren/ungit/issues/858)\n' + + ' - 1.1.6: Fix path auto complete [#861](https://github.com/FredrikNoren/ungit/issues/861)\n' + ' - 1.1.5: Update "Toggle all" button after commit or changing selected files [#859](https://github.com/FredrikNoren/ungit/issues/859)\n' + - " - 1.1.4: [patch] Promise refactoring\n" + - " \n"; + ' - 1.1.4: [patch] Promise refactoring\n' + + ' \n'; const result = html(diffExample2, { drawFileList: false }); expect(result).toMatchInlineSnapshot(` "
diff --git a/src/__tests__/file-list-printer-tests.ts b/src/__tests__/file-list-printer-tests.ts index 7ed1e32..0b09c60 100644 --- a/src/__tests__/file-list-printer-tests.ts +++ b/src/__tests__/file-list-printer-tests.ts @@ -1,14 +1,14 @@ -import { render } from "../file-list-renderer"; -import HoganJsUtils from "../hoganjs-utils"; +import { render } from '../file-list-renderer'; +import HoganJsUtils from '../hoganjs-utils'; -describe("FileListPrinter", () => { - describe("generateFileList", () => { - it("should expose old and new files to templates", () => { +describe('FileListPrinter', () => { + describe('generateFileList', () => { + it('should expose old and new files to templates', () => { const hoganUtils = new HoganJsUtils({ rawTemplates: { - "file-summary-wrapper": "{{{files}}}", - "file-summary-line": "{{oldName}}, {{newName}}, {{fileName}}" - } + 'file-summary-wrapper': '{{{files}}}', + 'file-summary-line': '{{oldName}}, {{newName}}, {{fileName}}', + }, }); const files = [ { @@ -17,9 +17,9 @@ describe("FileListPrinter", () => { blocks: [], addedLines: 12, deletedLines: 41, - language: "js", - oldName: "my/file/name.js", - newName: "my/file/name.js" + language: 'js', + oldName: 'my/file/name.js', + newName: 'my/file/name.js', }, { isCombined: false, @@ -27,9 +27,9 @@ describe("FileListPrinter", () => { blocks: [], addedLines: 12, deletedLines: 41, - language: "js", - oldName: "my/file/name1.js", - newName: "my/file/name2.js" + language: 'js', + oldName: 'my/file/name1.js', + newName: 'my/file/name2.js', }, { isCombined: false, @@ -37,10 +37,10 @@ describe("FileListPrinter", () => { blocks: [], addedLines: 12, deletedLines: 0, - language: "js", - oldName: "dev/null", - newName: "my/file/name.js", - isNew: true + language: 'js', + oldName: 'dev/null', + newName: 'my/file/name.js', + isNew: true, }, { isCombined: false, @@ -48,11 +48,11 @@ describe("FileListPrinter", () => { blocks: [], addedLines: 0, deletedLines: 41, - language: "js", - oldName: "my/file/name.js", - newName: "dev/null", - isDeleted: true - } + language: 'js', + oldName: 'my/file/name.js', + newName: 'dev/null', + isDeleted: true, + }, ]; const fileHtml = render(files, hoganUtils); @@ -65,7 +65,7 @@ describe("FileListPrinter", () => { `); }); - it("should work for all kinds of files", () => { + it('should work for all kinds of files', () => { const hoganUtils = new HoganJsUtils({}); const files = [ { @@ -74,9 +74,9 @@ describe("FileListPrinter", () => { blocks: [], addedLines: 12, deletedLines: 41, - language: "js", - oldName: "my/file/name.js", - newName: "my/file/name.js" + language: 'js', + oldName: 'my/file/name.js', + newName: 'my/file/name.js', }, { isCombined: false, @@ -84,9 +84,9 @@ describe("FileListPrinter", () => { blocks: [], addedLines: 12, deletedLines: 41, - language: "js", - oldName: "my/file/name1.js", - newName: "my/file/name2.js" + language: 'js', + oldName: 'my/file/name1.js', + newName: 'my/file/name2.js', }, { isCombined: false, @@ -94,10 +94,10 @@ describe("FileListPrinter", () => { blocks: [], addedLines: 12, deletedLines: 0, - language: "js", - oldName: "dev/null", - newName: "my/file/name.js", - isNew: true + language: 'js', + oldName: 'dev/null', + newName: 'my/file/name.js', + isNew: true, }, { isCombined: false, @@ -105,11 +105,11 @@ describe("FileListPrinter", () => { blocks: [], addedLines: 0, deletedLines: 41, - language: "js", - oldName: "my/file/name.js", - newName: "dev/null", - isDeleted: true - } + language: 'js', + oldName: 'my/file/name.js', + newName: 'dev/null', + isDeleted: true, + }, ]; const fileHtml = render(files, hoganUtils); expect(fileHtml).toMatchInlineSnapshot(` diff --git a/src/__tests__/hogan-cache-tests.ts b/src/__tests__/hogan-cache-tests.ts index 8e4011c..b229db2 100644 --- a/src/__tests__/hogan-cache-tests.ts +++ b/src/__tests__/hogan-cache-tests.ts @@ -1,13 +1,13 @@ -import HoganJsUtils from "../hoganjs-utils"; -import { CSSLineClass } from "../render-utils"; +import HoganJsUtils from '../hoganjs-utils'; +import { CSSLineClass } from '../render-utils'; -describe("HoganJsUtils", () => { - describe("render", () => { - it("should render view", () => { +describe('HoganJsUtils', () => { + describe('render', () => { + it('should render view', () => { const hoganJsUtils = new HoganJsUtils({}); - const result = hoganJsUtils.render("generic", "empty-diff", { - contentClass: "d2h-code-line", - CSSLineClass: CSSLineClass + const result = hoganJsUtils.render('generic', 'empty-diff', { + contentClass: 'd2h-code-line', + CSSLineClass: CSSLineClass, }); expect(result).toMatchInlineSnapshot(` "
-
- File without changes -
-