├── .circleci └── config.yml ├── .codecov.yml ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ └── dependabot-auto-merge.yml ├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── .yarnrc.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── angular-diff-match-patch.js ├── bower.json ├── index.html ├── index.js ├── jsconfig.json ├── package.json ├── test ├── diffmatchpatch-spec.js ├── karma-watch.conf.js └── karma.conf.js └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | orbs: 3 | codecov: codecov/codecov@5.2.1 4 | jobs: 5 | test: 6 | docker: 7 | - image: cimg/node:lts-browsers 8 | steps: 9 | - checkout 10 | - run: 11 | name: Enable corepack 12 | command: sudo corepack enable 13 | - run: 14 | name: Install packages 15 | command: yarn install 16 | - run: 17 | name: Run tests 18 | command: yarn test 19 | - codecov/upload 20 | - store_test_results: 21 | path: ./test/results/junit 22 | - store_artifacts: 23 | path: ./coverage 24 | - persist_to_workspace: 25 | root: ./ 26 | paths: 27 | - package.json 28 | - ./*.js 29 | - README.md 30 | resource_class: large 31 | 32 | deploy: 33 | docker: 34 | - image: cimg/node:lts-browsers 35 | steps: 36 | - attach_workspace: 37 | at: ./ 38 | - run: 39 | name: Set NPM token 40 | command: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 41 | - run: 42 | name: NPM Publish 43 | command: | 44 | if [ ! -z "$CIRCLE_TAG" ]; 45 | then npm publish; 46 | else echo " No tag found, no attempt to publish to npm. "; 47 | fi 48 | 49 | workflows: 50 | test-and-deploy: 51 | jobs: 52 | - test: 53 | filters: # required since `deploy` has tag filters AND requires `build` 54 | tags: 55 | only: /.*/ 56 | - deploy: 57 | requires: 58 | - test 59 | filters: 60 | tags: 61 | only: /^v.*/ 62 | branches: 63 | ignore: /.*/ 64 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | precision: 2 3 | round: down 4 | range: "70...100" 5 | 6 | comment: 7 | layout: "header, diff" 8 | behavior: default 9 | require_changes: true -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: "github-actions" 8 | directory: "/" 9 | schedule: 10 | interval: daily 11 | -------------------------------------------------------------------------------- /.github/workflows/dependabot-auto-merge.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-merge 2 | on: pull_request 3 | 4 | permissions: 5 | contents: write 6 | pull-requests: write 7 | 8 | jobs: 9 | dependabot: 10 | runs-on: ubuntu-latest 11 | if: ${{ github.actor == 'dependabot[bot]' }} 12 | steps: 13 | - name: Dependabot metadata 14 | id: metadata 15 | uses: dependabot/fetch-metadata@v2.4.0 16 | with: 17 | github-token: "${{ secrets.GITHUB_TOKEN }}" 18 | - name: Enable auto-merge for Dependabot PRs 19 | if: ${{steps.metadata.outputs.dependency-names}} 20 | run: gh pr merge --auto --merge "$PR_URL" 21 | env: 22 | PR_URL: ${{github.event.pull_request.html_url}} 23 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/bower_components/ 2 | **/node_modules/ 3 | **/coverage/ 4 | npm-debug.log 5 | test/results 6 | .DS_Store 7 | yarn-error.log 8 | .pnp.* 9 | .yarn/* 10 | !.yarn/patches 11 | !.yarn/plugins 12 | !.yarn/releases 13 | !.yarn/sdks 14 | !.yarn/versions 15 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "chrome", 6 | "request": "launch", 7 | "name": "Launch Chrome against localhost", 8 | "url": "http://127.0.0.1:8080/index.html", 9 | "webRoot": "${workspaceRoot}" 10 | }, 11 | { 12 | "type": "chrome", 13 | "request": "attach", 14 | "name": "Attach to Chrome", 15 | "port": 9222, 16 | "webRoot": "${workspaceRoot}" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.enable": false 3 | } -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [0.8.13](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.12...v0.8.13) (2024-07-08) 6 | 7 | ### [0.8.12](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.11...v0.8.12) (2024-07-08) 8 | 9 | ### [0.8.11](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.10...v0.8.11) (2024-07-08) 10 | 11 | ### [0.8.10](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.8...v0.8.10) (2024-07-08) 12 | 13 | ### [0.8.9](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.8...v0.8.9) (2024-07-08) 14 | 15 | ### [0.8.8](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.7...v0.8.8) (2023-01-19) 16 | 17 | ### [0.8.7](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.6...v0.8.7) (2023-01-19) 18 | 19 | ### [0.8.6](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.5...v0.8.6) (2022-09-07) 20 | 21 | ### [0.8.5](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.4...v0.8.5) (2022-02-11) 22 | 23 | ### [0.8.4](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.3...v0.8.4) (2022-02-10) 24 | 25 | ### [0.8.3](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.2...v0.8.3) (2021-11-20) 26 | 27 | ### [0.8.2](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.1...v0.8.2) (2021-10-13) 28 | 29 | ### [0.8.1](https://github.com/amweiss/angular-diff-match-patch/compare/v0.8.0...v0.8.1) (2021-05-14) 30 | 31 | ## [0.8.0](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.83...v0.8.0) (2021-04-21) 32 | 33 | 34 | ### ⚠ BREAKING CHANGES 35 | 36 | * use ES2015 stuff 37 | * use ES2015 stuff 38 | 39 | * Merge pull request #231 from amweiss/dependabot/npm_and_yarn/xo-0.39.1 ([0615dcf](https://github.com/amweiss/angular-diff-match-patch/commit/0615dcf1bb8bff577efa17c64b0964568026d604)), closes [#231](https://github.com/amweiss/angular-diff-match-patch/issues/231) 40 | * Fix linting ([ff7a7ed](https://github.com/amweiss/angular-diff-match-patch/commit/ff7a7edb91a6a433bf95e75ad0d5be3357eede1c)) 41 | 42 | ### [0.7.83](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.82...v0.7.83) (2021-03-01) 43 | 44 | ### [0.7.82](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.81...v0.7.82) (2021-03-01) 45 | 46 | ### [0.7.81](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.80...v0.7.81) (2021-01-07) 47 | 48 | ### [0.7.80](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.79...v0.7.80) (2021-01-07) 49 | 50 | ### [0.7.79](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.78...v0.7.79) (2020-11-20) 51 | 52 | ### [0.7.78](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.77...v0.7.78) (2020-08-06) 53 | 54 | ### [0.7.77](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.76...v0.7.77) (2020-05-08) 55 | 56 | ### [0.7.76](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.75...v0.7.76) (2020-04-24) 57 | 58 | 59 | ### Bug Fixes 60 | 61 | * **bug:** Fix [#148](https://github.com/amweiss/angular-diff-match-patch/issues/148) ([f2d162f](https://github.com/amweiss/angular-diff-match-patch/commit/f2d162f910eb0ca8ae475644eecbe7b32ef93275)) 62 | 63 | ### [0.7.75](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.74...v0.7.75) (2020-04-24) 64 | 65 | 66 | ### Bug Fixes 67 | 68 | * **bug:** Fix [#148](https://github.com/amweiss/angular-diff-match-patch/issues/148) ([d6390c2](https://github.com/amweiss/angular-diff-match-patch/commit/d6390c2459f35740f5c925e5e8ea63c5e5e2798d)) 69 | 70 | ### [0.7.74](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.52...v0.7.74) (2020-04-23) 71 | 72 | ### [0.7.52](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.28...v0.7.52) (2019-10-23) 73 | 74 | ## [0.7.28](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.4...v0.7.28) (2019-03-15) 75 | 76 | 77 | 78 | 79 | ## [0.7.4](https://github.com/amweiss/angular-diff-match-patch/compare/v0.7.0...v0.7.4) (2018-09-13) 80 | 81 | 82 | 83 | 84 | ## [0.7.0](https://github.com/amweiss/angular-diff-match-patch/compare/v0.6.23...v0.7.0) (2018-08-27) 85 | 86 | 87 | 88 | 89 | ## [0.6.23](https://github.com/amweiss/angular-diff-match-patch/compare/v0.6.15...v0.6.23) (2018-08-24) 90 | 91 | 92 | 93 | 94 | ## [0.6.16](https://github.com/amweiss/angular-diff-match-patch/compare/v0.6.15...v0.6.16) (2018-07-16) 95 | 96 | 97 | 98 | 99 | ## [0.6.15](https://github.com/amweiss/angular-diff-match-patch/compare/v0.6.14...v0.6.15) (2018-05-29) 100 | 101 | 102 | 103 | 104 | ## [0.6.14](https://github.com/amweiss/angular-diff-match-patch/compare/v0.6.13...v0.6.14) (2018-04-10) 105 | 106 | 107 | ### Bug Fixes 108 | 109 | * **demo:** Fix the js files in the local demo ([341edb0](https://github.com/amweiss/angular-diff-match-patch/commit/341edb0)) 110 | 111 | 112 | 113 | 114 | ## [0.6.13](https://github.com/amweiss/angular-diff-match-patch/compare/v0.6.12...v0.6.13) (2018-03-23) 115 | 116 | 117 | 118 | 119 | ## [0.6.12](https://github.com/amweiss/angular-diff-match-patch/compare/v0.6.11...v0.6.12) (2018-03-23) 120 | 121 | 122 | 123 | 124 | ## [0.6.11](https://github.com/amweiss/angular-diff-match-patch/compare/v0.6.10...v0.6.11) (2018-03-23) 125 | 126 | 127 | 128 | 129 | ## [0.6.10](https://github.com/amweiss/angular-diff-match-patch/compare/v0.6.9...v0.6.10) (2017-06-13) 130 | 131 | 132 | ### Bug Fixes 133 | 134 | * **ci:** cci2 config for npm publish ([1c8ac2b](https://github.com/amweiss/angular-diff-match-patch/commit/1c8ac2b)) 135 | 136 | 137 | 138 | 139 | ## [0.6.9](https://github.com/amweiss/angular-diff-match-patch/compare/v0.6.8...v0.6.9) (2017-06-13) 140 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Adam Weiss 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | angular-diff-match-patch 2 | ======================== 3 | 4 | [](https://www.npmjs.com/package/angular-diff-match-patch) 5 | [](https://circleci.com/gh/amweiss/angular-diff-match-patch/tree/master) [](https://codecov.io/gh/amweiss/angular-diff-match-patch) 6 | 7 | This library is simply a wrapper around [google-diff-match-patch](https://code.google.com/p/google-diff-match-patch/). 8 | 9 |  10 | 11 | (Shown here with some custom styles) 12 | 13 | Angular 2 Port 14 | --------------- 15 | 16 | Should you wish to use this in an Angular 2+ project, take a look at this port: [elliotforbes/ng-diff-match-patch](https://github.com/elliotforbes/ng-diff-match-patch) 17 | 18 | Setup 19 | ----- 20 | 21 | Install from [NPM](https://npmjs.com) 22 | 23 | `npm install amweiss/angular-diff-match-patch` 24 | 25 | Install from [Bower](https://bower.io/) 26 | 27 | `bower install angular-diff-match-patch` 28 | 29 | Usage with webpack 30 | 31 | ```javascript 32 | config.plugins = [ 33 | new webpack.ProvidePlugin({ 34 | diff_match_patch: 'diff-match-patch' 35 | }), 36 | ]; 37 | ``` 38 | 39 | Usage 40 | ----- 41 | 42 | See [the included demo](https://amweiss.github.io/angular-diff-match-patch/) for reference or view a sample on [Codepen](https://codepen.io/amweiss/pen/grXNPm). 43 | 44 | ```html 45 |
46 | ``` 47 | 48 | Where `left` and `right` are defined on your scope. The `options` attribute can be used as well, but it's optional. 49 | 50 | ```javascript 51 | $scope.options = { 52 | editCost: 4, 53 | attrs: { 54 | insert: { 55 | 'data-attr': 'insert', 56 | 'class': 'insertion' 57 | }, 58 | delete: { 59 | 'data-attr': 'delete' 60 | }, 61 | equal: { 62 | 'data-attr': 'equal' 63 | } 64 | } 65 | }; 66 | ``` 67 | 68 | `editCost` is specific to `processingDiff` and controls the tolerence for hunk separation. `attrs` can contain any/all/none of the following: `insert`, `delete`, and `equal` where the properties in those objects represent attributes that get added to the tags. 69 | 70 | Another option is to skip angular processing the diff, it's useful when you want to show a diff of a code pre-compiled by angular. The attribute you need to add is called: `skipAngularCompilingOnDiff`. If set to `true`, would skip compiling, otherwise it would compile the diff. 71 | 72 | Add some style 73 | 74 | ```css 75 | .match{ 76 | color: gray; 77 | } 78 | 79 | .ins{ 80 | color: black; 81 | background: #bbffbb; 82 | } 83 | 84 | .del{ 85 | color: black; 86 | background: #ffbbbb; 87 | } 88 | ``` 89 | 90 | Development 91 | ----- 92 | 93 | Development work requires npm from [Node.js](https://nodejs.org/) 94 | 95 | Begin with: 96 | 97 | `npm install` 98 | 99 | Then you can use: 100 | 101 | `npm start` To host the directory so you can see the demo 102 | 103 | `npm test` To run the Jasmine tests once 104 | 105 | `npm test-watch` To run the Jasmine tests with change detection 106 | -------------------------------------------------------------------------------- /angular-diff-match-patch.js: -------------------------------------------------------------------------------- 1 | /* 2 | angular-diff-match-patch 3 | http://amweiss.github.io/angular-diff-match-patch/ 4 | @license: MIT 5 | */ 6 | angular.module('diff-match-patch', []) 7 | .constant('DiffMatchPatch', diff_match_patch) 8 | .factory('DIFF_INSERT', ['DiffMatchPatch', function (DiffMatchPatch) { 9 | return DiffMatchPatch.DIFF_INSERT === undefined ? DIFF_INSERT : DiffMatchPatch.DIFF_INSERT; 10 | }]) 11 | .factory('DIFF_DELETE', ['DiffMatchPatch', function (DiffMatchPatch) { 12 | return DiffMatchPatch.DIFF_DELETE === undefined ? DIFF_DELETE : DiffMatchPatch.DIFF_DELETE; 13 | }]) 14 | .factory('dmp', ['DiffMatchPatch', 'DIFF_INSERT', 'DIFF_DELETE', function (DiffMatchPatch, DIFF_INSERT, DIFF_DELETE) { 15 | const displayType = { 16 | INSDEL: 0, 17 | LINEDIFF: 1, 18 | }; 19 | 20 | function diffClass(op) { 21 | switch (op) { 22 | case DIFF_INSERT: { 23 | return 'ins'; 24 | } 25 | 26 | case DIFF_DELETE: { 27 | return 'del'; 28 | } 29 | 30 | default: { // case DIFF_EQUAL: 31 | return 'match'; 32 | } 33 | } 34 | } 35 | 36 | function diffSymbol(op) { 37 | switch (op) { 38 | case DIFF_INSERT: { 39 | return '+'; 40 | } 41 | 42 | case DIFF_DELETE: { 43 | return '-'; 44 | } 45 | 46 | default: { // case DIFF_EQUAL: 47 | return ' '; 48 | } 49 | } 50 | } 51 | 52 | function diffTag(op) { 53 | switch (op) { 54 | case DIFF_INSERT: { 55 | return 'ins'; 56 | } 57 | 58 | case DIFF_DELETE: { 59 | return 'del'; 60 | } 61 | 62 | default: { // case DIFF_EQUAL: 63 | return 'span'; 64 | } 65 | } 66 | } 67 | 68 | function diffAttributeName(op) { 69 | switch (op) { 70 | case DIFF_INSERT: { 71 | return 'insert'; 72 | } 73 | 74 | case DIFF_DELETE: { 75 | return 'delete'; 76 | } 77 | 78 | default: { // case DIFF_EQUAL: 79 | return 'equal'; 80 | } 81 | } 82 | } 83 | 84 | function getTagAttributes(options, op, attributes) { 85 | const tagOptions = {}; 86 | const returnValue = []; 87 | const opName = diffAttributeName(op); 88 | 89 | if (angular.isDefined(options) && angular.isDefined(options.attrs)) { 90 | const attributesFromOptions = options.attrs[opName]; 91 | if (angular.isDefined(attributesFromOptions)) { 92 | angular.merge(tagOptions, attributesFromOptions); 93 | } 94 | } 95 | 96 | if (angular.isDefined(attributes)) { 97 | angular.merge(tagOptions, attributes); 98 | } 99 | 100 | if (Object.keys(tagOptions).length === 0) { 101 | return ''; 102 | } 103 | 104 | for (const [key, value] of Object.entries(tagOptions)) { 105 | returnValue.push(key + '="' + value + '"'); 106 | } 107 | 108 | return ' ' + returnValue.join(' '); 109 | } 110 | 111 | function getHtmlPrefix(op, display, options) { 112 | switch (display) { 113 | case displayType.LINEDIFF: { 114 | return '