Git Product home page Git Product logo

ace-diff's Introduction

Ace-diff

This is a wrapper for Ace Editor to provide a 2-panel diffing/merging tool that visualizes differences in two documents and allows users to copy changes from to the other.

Ace-diff demo

It's built on top of google-diff-match-patch library. That lib handles the hard part: the computation of the document diffs. Ace-diff just visualizes that information as line-diffs in the editors.

Dependencies

  • Ace Editor: this could the official Ace builds, Brace and any other similar Ace editor build (like the ones from public CDNs)

Demos

Take a look at demos on Ace-diff page. The demos illustrate a few different configurations and styles. Hopefully they'll give you a rough sense of what it does and how it works.

Features

  • Compatible with any Ace/Brace Editor mode or theme
  • Accommodates realtime changes to one or both editors
  • Readonly option for left/right editors
  • Control how aggressively diffs are combined
  • Allow users to copy diffs from one side to the other

How to install

npm i ace-diff -S

…

yarn add ace-diff
import AceDiff from 'ace-diff';

// optionally, include CSS, or use your own
import 'ace-diff/dist/ace-diff.min.css';
// Or use the dark mode
import 'ace-diff/dist/ace-diff-dark.min.css';

Use CDN

Grab ace-diff from CDN:

<!-- Inlude Ace Editor - e.g. with this: -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.13.1/ace.js"></script>

<script src="https://unpkg.com/ace-diff@^3.0.0"></script>

<!-- optionally include CSS, or use your own -->
<link href="https://unpkg.com/ace-diff@^3.0.0/dist/ace-diff.min.css" rel="stylesheet">

<!-- optionally there is also a dark mode CSS -->
<link href="https://unpkg.com/ace-diff@^3.0.0/dist/ace-diff-dark.min.css" rel="stylesheet">

HTML

<div class="acediff"></div>

JavaScript

Here's an example of how you'd instantiate AceDiff.

const differ = new AceDiff({
  ace: window.ace, // You Ace Editor instance
  element: '.acediff',
  left: {
    content: 'your first file content here',
  },
  right: {
    content: 'your second file content here',
  },
});

When using with Brace or any build system like Webpack, you can pass the editor as an option:

// If you are using Brace editor, you can pass it as well
const ace = require('brace');

const differ = new AceDiff({
  ace, // using Brace
  element: '.acediff',
  left: {
    content: 'your first file content here',
  },
  right: {
    content: 'your second file content here',
  },
});

CSS

Because of the way how ACE is positioned, it's important to have Ace-diff running in some container with specified dimensions (and optionally with a position: relative)

Styling the elements is vitally important: the gutter should retain its width even if the user resizes his or her browser. But honestly, how you go about that is very much up to you: you can provide whatever CSS you want, depending on your scenario.

If you want the ace editor's to change height/width based on a user's browser, I find using flexbox the best option - but hell, if you want to use a <table>, knock yourself out. :)

Take a look at the demos for some ideas. They all use flexbox for the layouts, but include some different styles and class names just so you can see.

Configuration

You can configure your Ace-diff instance through a number of config settings. This object is what you pass to the constructor, like the JavaScript section above.

Default settings

Here are all the defaults. I'll explain each one in details below. Note: you only need to override whatever you want.

{
  ace: window.ace,
  mode: null,
  theme: null,
  element: null,
  diffGranularity: 'broad',
  showDiffs: true,
  showConnectors: true,
  maxDiffs: 5000,
  left: {
    content: null,
    mode: null,
    theme: null,
    editable: true,
    copyLinkEnabled: true
  },
  right: {
    content: null,
    mode: null,
    theme: null,
    editable: true,
    copyLinkEnabled: true
  },
  classes: {
    diff: 'acediff__diffLine',
    connector: 'acediff__connector',
    newCodeConnectorLinkContent: '&#8594;',
    deletedCodeConnectorLinkContent: '&#8592;',
  },
}

Diffing settings

  • ace (object, optional, default: window.ace). The Ace Editor instance to use.
  • element (string or element object, required). The element used for Ace-diff
  • mode (string, optional). this is the mode for the Ace Editor, e.g. "ace/mode/javascript". Check out the Ace docs for that. This setting will be applied to both editors. I figured 99.999999% of the time you're going to want the same mode for both of them so you can just set it once here. If you're a mad genius and want to have different modes for each side, (a) whoah man, what's your use-case?, and (b) you can override this setting in one of the settings below. Read on.
  • theme (string, optional). This lets you set the theme for both editors.
  • diffGranularity (string, optional, default: broad). this has two options (specific, and broad). Basically this determines how aggressively AceDiff combines diffs to simplify the interface. I found that often it's a judgement call as to whether multiple diffs on one side should be grouped. This setting provides a little control over it.
  • showDiffs (boolean, optional, default: true). Whether or not the diffs are enabled. This basically turns everything off.
  • showConnectors (boolean, optional, default: true). Whether or not the gutter in the middle show show connectors visualizing where the left and right changes map to one another.
  • maxDiffs (integer, optional, default: 5000). This was added a safety precaution. For really massive files with vast numbers of diffs, it's possible the Ace instances or AceDiff will become too laggy. This simply disables the diffing altogether once you hit a certain number of diffs.
  • left/right. this object contains settings specific to the leftmost editor.
  • left.content / right.content (string, optional, default: null). If you like, when you instantiate AceDiff you can include the content that should appear in the leftmost editor via this property.
  • left.mode / right.mode (string, optional, defaults to whatever you entered in mode). This lets you override the default Ace Editor mode specified in mode.
  • left.theme / right.theme (string, optional, defaults to whatever you entered in theme). This lets you override the default Ace Editor theme specified in theme.
  • left.editable / right.editable (boolean, optional, default: true). Whether the left editor is editable or not.
  • left.copyLinkEnabled / right.copyLinkEnabled (boolean, optional, default: true). Whether the copy to right/left arrows should appear.

Classes

  • diff: the class for a diff line on either editor
  • connector: the SVG connector
  • newCodeConnectorLinkContent: the content of the copy to right link. Defaults to a unicode right arrow ('→')
  • deletedCodeConnectorLinkContent: the content of the copy to left link. Defaults to a unicode right arrow ('←')

API

There are a few API methods available on your AceDiff instance.

  • aceInstance.getEditors(): this returns an object with left and right properties. Each contains a reference to the Ace editor, in case you need to do anything with them. Ace has a ton of options which I wasn't going to support via the wrapper. This should allow you to do whatever you need
  • aceInstance.setOptions(): this lets you set many of the above options on the fly. Note: certain things used during the construction of the editor, like the classes can't be overridden.
  • aceInstance.getNumDiffs(): returns the number of diffs currently being displayed.
  • aceInstance.diff(): updates the diff. This shouldn't ever be required because AceDiff automatically recognizes the key events like changes to the editor and window resizing. But I've included it because there may always be that fringe case...
  • aceInstance.destroy(): destroys the AceDiff instance. Basically this just destroys both editors and cleans out the gutter.

Browser Support

All modern browsers. Open a ticket if you find otherwise.

License

MIT.

ace-diff's People

Contributors

benkeen avatar blanecordes avatar code1492 avatar dependabot[bot] avatar jackub avatar mustafahaddara avatar nicolashenry avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ace-diff's Issues

angular integration

Is it possible to integrate it with angular 7? Or there is already something existing ?

Thanks.

Incorrect demo version

Could you fix differences between Demo version and last release version, please?
The Demo version doesn't have element options and works fine, but the last release has it but doesn't explain how to use it.

Diffing error

Hello, I think I have found an error in the diffing display in the demos provided. I used the JSON objects pasted here on Demo 1 to check the diffing display, and it seems that the display on line 27 on the left side and 24-27 on the right side are incorrect.

I believe the correct display would be to highlight line 25 on the left side, and lines 23 and 24 on the right side.

image

css

unless one uses exactly your css with flexbox is virtually impossible to understand what to do - you should provide an other example, or minimal requirements like putting colors, alignment, etc. An example using a table or just divs could help people to understand what to do - also a minimal css for that - a very minimal css would be nice - one that dont use absolutes , relatives or flexbox - just inline/block. Also the gutter svg and others don't a have default colors and this makes really hard to understand how to make it work

something wrong with the \n

Hi,
In my project, there are some problems to show the difference.
bug

In the left editor, I think the line under line 1 should be moved to line 2.
In the right editor, the line under line 13 should be moved to line 14.

You can try the attached code to reproduce the bug.
errorCode.txt

Few Requirement in ace diff page .

Random Font size not working in ace diff page:
Ace diff font size is too small . If I change font-size in ace diff tool, diff connector is not working properly .
For Example :

Default Font size in ace diff :

default-font-size

Custom Font Size in ace diff is not properly connector working:

custom-fontsize

Set Use Word Wrap is not working :

wordwrap-issue

@nicolashenry @benkeen Diff compare is not a problem.But connectors only problem . Please my humble request fix it as soon as possible . Because we are using ace diff tool . Previously We have been using mergely tool .http://www.mergely.com/editor . It also so cool for showing diff and merge page .

I think there might be something wrong with the logic

I am using ace-diff v2.1.2.
In my source code, there are some errors

  1. In the right editor, the blue line should be drawn between line 35 and 36. For the source code before version 1.0.0, this works properly.
    image

  2. In the right editor, only line 150 should be marked. For the source code before version 1.0.0, this also works properly.
    image

  3. One new line at the end is not marked.
    image

Gutter SVG Path Wrong On Ace 1.3.3 With Ace-Diff 2.1.1

I was originally using Ace 1.3.3 since it was recently released. However, I noticed that ace-diff 2.1.1 connectors/svg path don't seem to calculate correctly on this version of ace. All paths are placed at the very top of the gutter, so it's hard to match changes to left/right sides and vice versa.

Rolling back to ace 1.2.5 corrected the issue, so it seems to be related to version of ace and not other issues in setup.

Known issue?

Need help with the css for ace-diff element

I am pretty sure this is css question and might not be related to ace-diff. However, I am having tough time finding a solution online and wanted to know if you have come across a solution for this simple problem.

I am trying to use ace-diff as yml editor and want to place a submit button right after the acediff content. I have currently managed to get it working to this point:
image
As you can see, my button is at the top of acediff content currently. I want it so that I can position button after the acediff element. Since acediff ONLY seems to work in absolute position, I am having a hard time placing button correctly on the html page.
html:

<div class="wrapper">
  <h3>Edit Application </h3>
  <div class="acediff"></div>
  <div class="submit-editor-button">
    <button class="ui button teal"
            type="button"
            (click)="save()">Save</button>
  </div>
</div>

css:

.acediff {
  position: absolute;
  left: 0;
  height: 75%;
  width: 100%;
}

.wrapper {
  position: static;
}

.submit-editor-button {
  position: absolute;
}

Help is greatly appreciated. Thank you.
(Sorry about creating an issue but I'm hoping it will be helpful to other css newbies like me trying to use acediff.)

diffs not lining up

It finds the diffs correctly but the gutter does not display properly and the highlighting are off. I believe it is caused by the line height.

blue_steel_cpm_and_blue_steel_cpm_and_datepicker_widget___jquery_ui_api_documentation

Diff not computed correctly if the text lines end with \r\n

If you populate the editors with content that has both the CR and LF characters at the end of each line (for example, importing a file from a Linux environment), the diff is not computed correctly.

I suspect that it's the way the line lengths are computed in this method: getLineLengths.

Here is an example of how it behaves in this case:
screen shot 2015-04-07 at 09 33 22

Incorrect highlighting

I have 2 version of a code with one different value of var:
left:

(function (window, $) {

    var sourceId, targetId, item,
        leftSource, rightSource,
        aceDiffer;
    $(document).ready(function () {
        sourceId = $("#source").val();
        targetId = $("#target").val();
        item = $("#item").val();

        aceDiffer = new AceDiff({
            element: '#diffs-container',
            mode: "",
            left: {
                editable: false,
                copyLinkEnabled: false,
                content: ''
            },
            right: {
                editable: false,
                copyLinkEnabled: false,
                content: ''
            }
        });

})(window, jQuery);

right:

(function (window, $) {

    var sourceId, targetId, item,
        leftSource, rightSource,
        aceDiffer;
    $(document).ready(function () {
        sourceId = $("#source").val();
        targetId = $("#target").val();
        item = $("#item").val();

        aceDiffer = new AceDiff({
            element: '#diffs-container',
            mode: "",
            left: {
                editable: false,
                copyLinkEnabled: true,
                content: ''
            },
            right: {
                editable: false,
                copyLinkEnabled: false,
                content: ''
            }
        });

})(window, jQuery);

The diff is in left.copyLinkEnabled, left code has false, right has true but ace-diff marks the next line of the editors like it has the diff. Where is the issue?

Diff navigation

I was demoing ace-diff when a developer asked if there was any way of navigating the diffs. The example that was loaded had 2 one-line diffs in a 1000 line file - and having to scroll up and down to find it was rather challenging :)

Is there any way of going to "the next diff", or only showing the previous / next lines of code relative to a diff (ie in this case hiding 990 lines of identical code)

Strange lines get inserted in the wrong place or diff computed wrong

Im not sure what is causing the issue, but ive seen several cases where doing a copy actually results in new differences. ive attached two files that you can paste into the respective editors. copy the difference in the fileb side to the filea side and you'll see a new difference is then created for the blank line after the original difference. Not sure if this is line ending related or diff related?

fileb.txt
filea.txt

Semi-colon causes the diff to insert incorrectly

In the first attached image the semi-colon on the right seems to be causing an issue.
The semi-colon only exists in the right pane, where-as in the left pane it exists further down after some further parameters have been added. The code therefore wants to insert the additional code from the left-pane above the code on the right, but it should include and replace the bottom line on the right.
chrome_2018-03-19_16-55-49

This second attachment shows what I'd expect to happen. I've simply replaced the semi-colon with another random charcter '>' to prove my point:
chrome_2018-03-19_16-59-02

Please can you help me with escaping semi-colons or suggest a fix?

Question/ Feature request

Hi,
Is there something that can be done the will compare text without leading and trailing spaces of all kind ( tab, cr cf etc.), some way/attribute to disregard spaces in the comparison.
ex.

file content 1:
1: test1
file content 2:
1:test1

currently i will get row #1 marked as containing a change but the texts are the same i would like to be able to decide which result i want
Cheers
idan.

There is strange logic in code

When I use ace-diff I'm equaling it with diff-merge by TortoiseSVN or TortoiseGit and I think that the left side is previous version of code and the right side is mine or next version of code. So as I know diff_match_patch provides a method - diff_make(arg1, arg2), which finds difference between arg1 and arg2 which have need added to arg1 for getting arg2. But inside the ace-diff code I find the next lines

const dmp = new DiffMatchPatch();
const val1 = this.editors.left.ace.getSession().getValue();
const val2 = this.editors.right.ace.getSession().getValue();
const diff = dmp.diff_main(val2, val1);

Is It correct to use val2, from ace.right, like "text from", and val1, from ace.left, like "text to"?
Also diff_match_patch provides methods dmp.diff_text1(diffs) and dmp.diff_text2(diffs) the first one returns text from ace.right and the second one returns text from ace.left. It looks like a bug.

Getting "Uncaught RangeError: Maximum call stack size exceeded" with boiler-plate code

I'm trying to test with boiler-plate code below, and am getting "Uncaught RangeError: Maximum call stack size exceeded". Any ideas? Thanks.

<html>
    <head>   
        <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.11/ace.js"></script>
        <script src="https://unpkg.com/ace-diff@^3"></script>
        <link href="https://unpkg.com/ace-diff@^3/dist/ace-diff.min.css" rel="stylesheet">
    </head>
    <body>
        <div class="acediff"></div>
        <script>
            const differ = new AceDiff({
                ace: window.ace,
                element: '.acediff',
                left: {
                    content: 'your first file content here',
                },
                right: {
                    content: 'your second file content here',
                },
            });
        </script>
    </body>
</html>

aceEditor.setValue vs aceEditor.replace

Why don't you use aceEditor.replace for inserting text but use setValue? As i know setValue clears undoredo manager after that impossible to use Ctrl+Z/Y.

Support ace-builds (instead of/in addition to) brace

ERROR in ./node_modules/ace-diff/src/index.js
Module not found: Error: Can't resolve 'brace' in '.../node_modules/ace-diff/src'

brace is updated infrequently (if at all, it really hasn't been changed in years).

ace-builds is maintained by the team that builds ace, and supports use via webpack/browserify. There's really no reason to specifically require brace anymore.

display none breaks gutter

if the editors are display:none and then set to be displayed the SVG and gutter arrows break because of width and height calculations see https://github.com/benkeen/ace-diff/blob/master/dist/ace-diff.js#L87
and
https://github.com/benkeen/ace-diff/blob/master/dist/ace-diff.js#L684
https://github.com/benkeen/ace-diff/blob/master/dist/ace-diff.js#L685

i have a fork and i've put in some defaults that basically match the default vaules for ace editor.

i can send a PR but i'm not sure if hard coding the values is really the best alternative. might be better to check the display property and if it is none, then clone the editors and inject them into the dom off the page and then set the dimensions and then destroy the cloned nodes.

Cannot read property 'acequire' of undefined

 ● Test suite failed to run

    TypeError: Cannot read property 'acequire' of undefined
    
at Object.<anonymous> (node_modules/ace-diff/src/index.js:12:35)

Can you think of anything that might be breaking this? @JackuB Please help!

Suggestion: Add a callback when diff is ready

Hi,

In a project I'm working on, I need to automatically scroll to the first diff available and give the user the ability to navigate to previous/next diff.

The issue I'm facing is that there is no event or callback sent to tell when ace-diff is done computing and displaying the diffs.

I've read somewhere that there might be a diff navigation in the works, but in a short term could it be possible to expose a "ready" callback in the ace-diff api?

Cheers!

Comparer display

Hi,

Is it possible to display the comparer among other controls in a page, without filling the entire page?

How do I use public API for the AceInstance?

Hi,
I am kind of new to javascript.
I created a new acediff element with

this.aceDiffer = new AceDiff({
      element: '.acediff',
      left: {
        content: this.originalYaml,
        editable: false
      },
      right: {
        content: this.applicationYaml,
        copyLinkEnabled: false
      },
    });

Say I want to get content in right panel, how do I get it?

console.log('Right content: ' + JSON.stringify(this.aceDiffer.getEditors().right.content));

gives undefined.

Bower package out of date

Hey @gad2103, I see you added your fork to bower but it's not in sync. I spent a long time figuring out why my ace-diff dist wasn't working with brace, and it's because you haven't updated pulled your fork since 2015. If you're not going to keep that fork up to date, you should namespace the project so other people aren't pulling in your personal changes. Can we get bower ace-diff to point to the main repo?

https://github.com/gad2103/ace-diff

Warning from webpack when using ace-diff 3

WARNING in ./node_modules/ace-diff/dist/ace-diff.min.js 1:292-296
Critical dependency: the request of a dependency is an expression

I suspect ace-diff is doing some dynamic require that webpack doesn't like. FYI I think webpack is fine with having require statements that are conditionally executed but has trouble with dynamic expressions in the require call itself. Could the code be refactored somehow to improve this?

Thanks for all the hard work on this library!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.