{"id":13583595,"url":"https://github.com/wickedest/Mergely","last_synced_at":"2025-04-06T21:32:34.429Z","repository":{"id":44899168,"uuid":"3640908","full_name":"wickedest/Mergely","owner":"wickedest","description":"Merge and diff documents online","archived":false,"fork":false,"pushed_at":"2025-01-17T17:10:33.000Z","size":1752,"stargazers_count":1211,"open_issues_count":22,"forks_count":233,"subscribers_count":47,"default_branch":"master","last_synced_at":"2025-04-03T05:06:57.860Z","etag":null,"topics":["diff","hacktoberfest"],"latest_commit_sha":null,"homepage":"http://www.mergely.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wickedest.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-03-06T18:06:46.000Z","updated_at":"2025-04-01T07:56:13.000Z","dependencies_parsed_at":"2023-02-08T07:01:11.092Z","dependency_job_id":"e293a19b-6687-488b-bc2f-978aaf122c88","html_url":"https://github.com/wickedest/Mergely","commit_stats":{"total_commits":215,"total_committers":22,"mean_commits":9.772727272727273,"dds":0.4372093023255814,"last_synced_commit":"da71745c3840df456a9cfeb80e106fc465c42577"},"previous_names":[],"tags_count":56,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wickedest%2FMergely","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wickedest%2FMergely/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wickedest%2FMergely/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wickedest%2FMergely/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wickedest","download_url":"https://codeload.github.com/wickedest/Mergely/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247556024,"owners_count":20957883,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["diff","hacktoberfest"],"created_at":"2024-08-01T15:03:37.294Z","updated_at":"2025-04-06T21:32:34.422Z","avatar_url":"https://github.com/wickedest.png","language":"JavaScript","readme":"# Mergely\n\n![mergely logo](https://www.mergely.com/images/mergely.png)\n\nhttps://mergely.com\n\nMergely is a JavaScript component for differencing and merging files interactively in a browser (diff/merge). It provides a rich API that enables you to easily integrate Mergely into your existing web application. It is suitable for comparing text files online, such as .txt, .html, .xml, .c, .cpp, .java, .js, etc.\n\nMergely has a JavaScript implementation of the Longest Common Subsequence (LCS) diff algorithm, and a customizable markup engine. It computes the diff within the browser.\n\nThis is the latest version 5. The previous version 4 can be found [here](https://github.com/wickedest/Mergely/tree/v4.3.9#mergely).\n\n## Usage\n\n### Usage via React\n\nThe easiest and recommended way to use Mergely is with the [mergely-react](https://npmjs.com/package/mergely-react) component.\n\n```bash\nnpm install mergely-react\n```\n\n### Usage via Angular\n\nThere is an Angular component for Mergely [mergely-angular](https://github.com/wickedest/mergely-angular), but it is out of date. I will accept MR for anyone willing to do the work.\n\n### Usage via webpack\n\nThe source repository [mergely-webpack](https://github.com/wickedest/mergely-webpack) contains an example of how to get started with a new project that uses mergely and webpack.\n\n```\ngit clone --depth 1 https://github.com/wickedest/mergely-webpack.git my-project\ncd my-project\nrm -rf .git\n```\n\n### Usage via CDN\n\nAdd the following to the `\u003chead\u003e` of your target HTML source file. Note that `codemirror` is bundled.\n\n```html\n\u003cscript type=\"text/javascript\" src=\"https://cdnjs.cloudflare.com/ajax/libs/mergely/5.0.0/mergely.min.js\"\u003e\u003c/script\u003e\n\u003clink type=\"text/css\" rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/mergely/5.0.0/mergely.css\" /\u003e\n```\n\n### Synchronous initialization\n\nIf the editor contents are retrieved asynchronously (recommended), then retrieve the editor contents and set them:\n\n```html\n\u003cbody\u003e\n  \u003cdiv id=\"compare\"\u003e\u003c/div\u003e\n\n  \u003cscript\u003e\n    const doc = new Mergely('#compare', {\n      lhs: 'the quick red fox\\njumped over the hairy dog',\n      rhs: 'the quick brown fox\\njumped over the lazy dog'\n    });\n  \u003c/script\u003e\n\u003c/body\u003e\n```\n\n### Asynchronous initialization\n\nMergely will emit an `updated` event when the editor is first initialized, and each time one of the editors changes. You can listen for one event to perform one-time initialization.\n\n```html\n\u003cbody\u003e\n  \u003cdiv id=\"compare\"\u003e\u003c/div\u003e\n\n  \u003cscript\u003e\n    const doc = new Mergely('#compare');\n    doc.once('updated', () =\u003e {\n      doc.lhs('the quick red fox\\njumped over the hairy dog');\n      doc.rhs('the quick brown fox\\njumped over the lazy dog');\n      // Scroll to first change on next update\n      doc.once('updated', () =\u003e {\n        doc.scrollToDiff('next');\n      });\n    });\n  \u003c/script\u003e\n\u003c/body\u003e\n```\n\n### Visualization modes\n\nMergely does not support any CodeMirror highlighting for different languages (xml, html, javascript etc.) out of the box.\nYou can compile your own Mergely-Version with support for the desired modes by adding them to diff-view.js. For example:\n```\nrequire('codemirror/mode/go/go.js');\nrequire('codemirror/mode/javascript/javascript.js');\nrequire('codemirror/mode/htmlmixed/htmlmixed.js');\nrequire('codemirror/mode/markdown/markdown.js');\nrequire('codemirror/mode/python/python.js');\n```\n\n## Options\n\n|Option|Type|Default value|Description|\n|------|----|-------------|-----------|\n|\u003ca name=\"autoupdate\"\u003e\u003c/a\u003eautoupdate|boolean|true|Controls whether or not the [`changed`](#changed) event will trigger a diff.|\n|\u003ca name=\"bgcolor\"\u003e\u003c/a\u003ebgcolor|string|`#eeeeee`|The background color for the left-hand and right-hand margins.|\n|\u003ca name=\"change_timeout\"\u003e\u003c/a\u003echange_timeout|number|`150`|The timeout, after a text change, before Mergely calculates a diff. Only used when `readonly` is enabled.|\n|\u003ca name=\"cmsettings\"\u003e\u003c/a\u003ecmsettings|object|`{mode: 'text/plain', readOnly: false}`|CodeMirror settings (see [CodeMirror](https://codemirror.net)) that are combined with `lhs_cmsettings` and `rhs_cmsettings`.|\n|\u003ca name=\"ignorews\"\u003e\u003c/a\u003eignorews|boolean|`false`|Ignores white-space.|\n|\u003ca name=\"ignorecase\"\u003e\u003c/a\u003eignorecase|boolean|`false`|Ignores case.|\n|\u003ca name=\"ignoreaccents\"\u003e\u003c/a\u003eignoreaccents|boolean|`false`|Ignores accented characters.|\n|\u003ca name=\"lcs\"\u003e\u003c/a\u003elcs|boolean|`true`|Enables/disables LCS computation for paragraphs (char-by-char changes). Disabling can give a performance gain for large documents.|\n|\u003ca name=\"lhs\"\u003e\u003c/a\u003elhs|boolean,`function handler(setValue)`|`null`|Sets the value of the editor on the left-hand side.|\n|\u003ca name=\"license\"\u003e\u003c/a\u003elicense|string|`lgpl`|The choice of license to use with Mergely.  Valid values are: `lgpl`, `gpl`, `mpl` or `lgpl-separate-notice`, `gpl-separate-notice`, `mpl-separate-notice` (the license requirements are met in a separate notice file).|\n|\u003ca name=\"line_numbers\"\u003e\u003c/a\u003eline_numbers|boolean|`true`|Enables/disables line numbers. Enabling line numbers will toggle the visibility of the line number margins.|\n|\u003ca name=\"lhs_cmsettings\"\u003e\u003c/a\u003elhs_cmsettings|object|`{}`|The CodeMirror settings (see [CodeMirror](https://codemirror.net)) for the left-hand side editor.|\n|\u003ca name=\"resize_timeout\"\u003e\u003c/a\u003eresize_timeout|number|`500`|The timeout, after a resize, before Mergely auto-resizes. Only used when autoresize enabled.|\n|\u003ca name=\"rhs\"\u003e\u003c/a\u003erhs|boolean,`function handler(setValue)`|`null`|Sets the value of the editor on the right-hand side.|\n|\u003ca name=\"rhs_cmsettings\"\u003e\u003c/a\u003erhs_cmsettings|object|`{}`|The CodeMirror settings (see [CodeMirror](https://codemirror.net)) for the right-hand side editor.|\n|\u003ca name=\"rhs_margin\"\u003e\u003c/a\u003erhs_margin|string|`right`|Location for the rhs markup margin. Possible values: right, left.|\n|\u003ca name=\"sidebar\"\u003e\u003c/a\u003esidebar|boolean|`true`|Enables/disables sidebar markers. Disabling can give a performance gain for large documents.|\n|\u003ca name=\"vpcolor\"\u003e\u003c/a\u003evpcolor|string|`rgba(0, 0, 200, 0.5)`|The margin/viewport indicator color.|\n|\u003ca name=\"viewport\"\u003e\u003c/a\u003eviewport|boolean|`false`|Enables/disables the viewport. Enabling the viewport can give a performance gain for large documents.|\n|\u003ca name=\"wrap_lines\"\u003e\u003c/a\u003ewrap_lines|boolean|`false`|Enables/disables line wrapping. Enabling wrapping will wrap text to fit the editors.|\n\n## Constructor\n\n### \u003ca name=\"constructor\"\u003e\u003c/a\u003econstructor(selector: string, options?: \u003ca href=\"#options\"\u003eobject\u003c/a\u003e)\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|selector|string|A CSS selector used to uniquely identify the DOM element that should be used to bind the instance of Mergely.|\n|options|object|Configuration options for the instance.|\n\n#### Example\n\n```js\nnew Mergely('#editor', { ignorews: true });\n```\n\n## Methods\n\n### \u003ca name=\"clear\"\u003e\u003c/a\u003eclear(side: string)\n\nClears the editor contents for the specified `side`.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|side|string|The editor side, either `lhs` or `rhs`.|\n\n#### Example\n\n```js\ndoc.clear('lhs');\n```\n\n### \u003ca name=\"cm\"\u003e\u003c/a\u003ecm(side: string)\n\nGets the CodeMirror editor for the specified `side`.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|side|string|The editor side, either `lhs` or `rhs`.|\n\n#### Example\n\n```js\ndoc.cm('lhs');\n```\n\n### \u003ca name=\"diff\"\u003e\u003c/a\u003ediff()\n\nCalculates and returns the current .diff file.\n\n#### Parameters\n\nNone.\n\n#### Example\n\n```js\ndoc.diff();\n```\n\n### \u003ca name=\"get\"\u003e\u003c/a\u003eget(side: string)\n\nGets the text editor contents for the specified `side`.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|side|string|The editor side, either `lhs` or `rhs`.|\n\n#### Example\n\n```js\ndoc.get('lhs');\n```\n\n### \u003ca name=\"lhs\"\u003e\u003c/a\u003elhs(value: string)\n\nSets the value of the left-hand editor.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|value|string|The editor text.|\n\n#### Example\n```js\ndoc.lhs('This is text');\n```\n\n### \u003ca name=\"merge\"\u003e\u003c/a\u003emerge(side: string)\n\nMerges whole file from the specified `side` to the opposite side.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|side|string|The editor side, either `lhs` or `rhs`.|\n\n#### Example\n\n```js\ndoc.merge('lhs');\n```\n\n### \u003ca name=\"mergeCurrentChange\"\u003e\u003c/a\u003emergeCurrentChange(side: string)\n\nMerges the current change from the specified `side` to the opposite side.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|side|string|The editor side, either `lhs` or `rhs`.|\n\n#### Example\n\n```js\ndoc.mergeCurrentChange('lhs');\n```\n\n### \u003ca name=\"on\"\u003e\u003c/a\u003eon(event: string, handler: function)\n\nSets up a `function` to be called when the specified `event` is emitted. The event handler will be automatically deregistered on \u003ca href=\"#unbind\"\u003eunbind\u003c/a\u003e.\n\n#### Parameters\n\nNone.\n\n#### Example\n\n```js\ndoc.on('updated', () =\u003e console.log('updated!'));\n```\n\n### \u003ca name=\"once\"\u003e\u003c/a\u003eonce(event: string, handler: function)\n\nSets up a `function` to be called when the specified `event` is emitted. The event handler will be automatically deregistered after the `handler` is called.\n\n#### Parameters\n\nNone.\n\n#### Example\n\n```js\ndoc.unbind();\n```\n\n### \u003ca name=\"options\"\u003e\u003c/a\u003eoptions(options?: \u003ca href=\"#options\"\u003eobject\u003c/a\u003e)\n\nGets or sets the editor \u003ca href=\"#options\"\u003eOptions\u003c/a\u003e. With no arguments, the function will return the currenty configured options. When supplied options to change, the editor will automatically update with the new settings.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|options|object|The options to set.|\n\n#### Example\n\n```js\nconst currentOptions = doc.options();\ndoc.options({ line_numbers: true });\n```\n\n### \u003ca name=\"resize\"\u003e\u003c/a\u003eresize()\n\nResizes the editor. It must be called explicitly if `autoresize` is disabled.\n\n#### Parameters\n\nNone.\n\n#### Example\n\n```js\ndoc.resize();\n```\n\n### \u003ca name=\"rhs\"\u003e\u003c/a\u003erhs(value: string)\n\nSets the value of the right-hand editor.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|value|string|The editor text.|\n\n#### Example\n\n```js\ndoc.rhs('This is text');\n```\n\n### \u003ca name=\"scrollTo\"\u003e\u003c/a\u003escrollTo(side: string, lineNum: integer)\n\nScrolls the editor `side` to line number specified by `lineNum`.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|side|string|The editor side, either `lhs` or `rhs`.|\n|lineNum|number|The line number.|\n\n#### Example\n\n```js\ndoc.scrollTo('lhs', 100);\n```\n\n### \u003ca name=\"scrollToDiff\"\u003e\u003c/a\u003escrollToDiff(direction: string)\n\nScrolls to the next change specified by `direction`.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|direction|string|The direction to scroll, either `prev` or `next`.|\n\n#### Example\n\n```js\ndoc.scrollToDiff('next');\n```\n\n### \u003ca name=\"search\"\u003e\u003c/a\u003esearch(side: string, needle: string, direction: string = 'next')\n\nSearch the editor for `needle`, scrolling to the next available match. Repeating the call will find the next available token.\n\n#### Parameters\n\n|Name|Type|Description|\n|----|----|-----------|\n|side|string|The editor side, either `lhs` or `rhs`.|\n|needle|string|The text for which to search.|\n|direction|string|The direction to search, either `prev` or `next`.|\n\n#### Example\n\n```js\ndoc.search('lhs', 'banana');\n```\n\n### \u003ca name=\"summary\"\u003e\u003c/a\u003esummary()\n\nGets a summary of the editors. Returns an object with summarized properties:\n\n|Name|Description|\n|----|-----------|\n|a|The number of added lines.|\n|c|The number of changed lines.|\n|d|The number of deleted lines.|\n|lhsLength|The number of characters in the lhs text.|\n|rhsLength|The number of characters in the rhs text.|\n|numChanges|The total number of changed lines.|\n\n#### Parameters\n\nNone.\n\n#### Example\n\n```js\nconsole.log(doc.summary());\n// { a: 0, c: 1, d: 0, lhsLength: 44, rhsLength: 45, numChanges: 1 }\n```\n\n### \u003ca name=\"swap\"\u003e\u003c/a\u003eswap()\n\nSwaps the content of the left and right editors. The content cannot be swapped if either editor is read-only.\n\n#### Parameters\n\nNone.\n\n#### Example\n\n```js\ndoc.swap();\n```\n\n### \u003ca name=\"unmarkup\"\u003e\u003c/a\u003eunmarkup()\n\nClears the editor markup.\n\n#### Parameters\n\nNone.\n\n#### Example\n\n```js\ndoc.unmarkup();\n```\n\n### \u003ca name=\"unbind\"\u003e\u003c/a\u003eunbind()\n\nUnbinds and destroys the editor DOM.\n\n#### Parameters\n\nNone.\n\n#### Example\n\n```js\ndoc.unbind();\n```\n\n## Events\n\nEvent handlers are automatically unregistered when [unbind](#unbind) is called.\n\n### changed\n\nTriggered when one of the editors change, e.g. text was altered. The [change_timeout](#/change_timeout) controls how much time should pass after the `changed` event (e.g. keypress) before the [`updated`](#updated) event is triggered.\n\n#### Example\n\n```js\nmergely.once('changed', () =\u003e { console.log('changed!'); }\n\nmergely.on('changed', () =\u003e { console.log('changed!'); }\n```\n\n### resized\n\nTriggered after the editor is resized.\n\n#### Example\n\n```js\nmergely.once('resized', () =\u003e { console.log('resized!'); }\n\nmergely.on('resized', () =\u003e { console.log('resized!'); }\n```\n\n### updated\n\nTriggered after the editor finishes rendering. For example, text updates, options, or scroll events may trigger renders. This event is useful for handling a once-off initialization that should occur after the editor's first render.\n\n#### Example\n\n```js\nmergely.once('updated', () =\u003e { console.log('updated!'); }\n\nmergely.on('updated', () =\u003e { console.log('updated!'); }\n```\n","funding_links":[],"categories":["JavaScript","hacktoberfest"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwickedest%2FMergely","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwickedest%2FMergely","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwickedest%2FMergely/lists"}