1
0
mirror of synced 2025-12-12 09:23:21 +08:00

Compare commits

..

20 Commits

Author SHA1 Message Date
Jamie Peabody
d1bad4868f fix(chore): updated deps 2024-05-06 09:33:10 +01:00
Jamie Peabody
bc54fce1c5 fix(chore): updated deps 2024-05-06 09:03:07 +01:00
dependabot[bot]
e7357e4ff1 build(deps-dev): bump express from 4.18.2 to 4.19.2 (#192)
Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 08:46:36 +01:00
dependabot[bot]
a673d33e89 build(deps-dev): bump webpack-dev-middleware from 5.3.3 to 5.3.4 (#191)
Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v5.3.3...v5.3.4)

---
updated-dependencies:
- dependency-name: webpack-dev-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 08:45:26 +01:00
dependabot[bot]
4818e05d2d build(deps-dev): bump follow-redirects from 1.15.2 to 1.15.6 (#190)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.2 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.2...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-06 08:43:52 +01:00
semantic-release-bot
07f32b9a7d chore(release): 5.1.2 [skip ci]
## [5.1.2](https://github.com/wickedest/Mergely/compare/v5.1.1...v5.1.2) (2024-05-06)

### Bug Fixes

* trace only when debug enabled ([#194](https://github.com/wickedest/Mergely/issues/194)) ([60d18f8](60d18f8d5c))
2024-05-06 07:42:38 +00:00
Jamie Peabody
60d18f8d5c fix: trace only when debug enabled (#194) 2024-05-06 08:41:30 +01:00
semantic-release-bot
4bd19c6e2e chore(release): 5.1.1 [skip ci]
## [5.1.1](https://github.com/wickedest/Mergely/compare/v5.1.0...v5.1.1) (2024-03-11)

### Bug Fixes

* **#183:** fixes undefined 'k' due to scoped 'let' ([02e383d](02e383d94d))
2024-03-11 19:46:42 +00:00
Jamie Peabody
02e383d94d fix(#183): fixes undefined 'k' due to scoped 'let' 2024-03-11 19:45:47 +00:00
dependabot[bot]
b09671febe build(deps-dev): bump @babel/traverse from 7.21.4 to 7.23.2 (#181)
Bumps [@babel/traverse](https://github.com/babel/babel/tree/HEAD/packages/babel-traverse) from 7.21.4 to 7.23.2.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-traverse)

---
updated-dependencies:
- dependency-name: "@babel/traverse"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-11 19:40:31 +00:00
dependabot[bot]
1702bd6e0a build(deps-dev): bump postcss from 8.4.21 to 8.4.31 (#180)
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.21 to 8.4.31.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.21...8.4.31)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-11 19:40:09 +00:00
semantic-release-bot
5e4dfc9e78 chore(release): 5.1.0 [skip ci]
# [5.1.0](https://github.com/wickedest/Mergely/compare/v5.0.4...v5.1.0) (2023-08-27)

### Features

* support CM modes: go, javascript, htmlmixed, markdown, python ([827487a](827487a598))
2023-08-27 13:04:50 +00:00
Jamie Peabody
827487a598 feat: support CM modes: go, javascript, htmlmixed, markdown, python 2023-08-27 14:03:41 +01:00
semantic-release-bot
bc46617d5e chore(release): 5.0.4 [skip ci]
## [5.0.4](https://github.com/wickedest/Mergely/compare/v5.0.3...v5.0.4) (2023-08-27)

### Bug Fixes

* updated CDN example ([dec1e95](dec1e9509d))
2023-08-27 12:17:49 +00:00
Jamie Peabody
dec1e9509d fix: updated CDN example 2023-08-27 13:16:11 +01:00
semantic-release-bot
0733f3a6c6 chore(release): 5.0.3 [skip ci]
## [5.0.3](https://github.com/wickedest/Mergely/compare/v5.0.2...v5.0.3) (2023-08-27)

### Bug Fixes

* Updated docs with CDN example ([254adf1](254adf15ab))
2023-08-27 10:55:22 +00:00
Jamie Peabody
254adf15ab fix: Updated docs with CDN example 2023-08-27 11:53:55 +01:00
Jamie Peabody
a07073a13c docs: Updated docs with CDN example 2023-08-27 11:50:00 +01:00
dependabot[bot]
3facfec6b7 build(deps): bump socket.io-parser from 4.2.2 to 4.2.3 (#177)
Bumps [socket.io-parser](https://github.com/socketio/socket.io-parser) from 4.2.2 to 4.2.3.
- [Release notes](https://github.com/socketio/socket.io-parser/releases)
- [Changelog](https://github.com/socketio/socket.io-parser/blob/main/CHANGELOG.md)
- [Commits](https://github.com/socketio/socket.io-parser/compare/4.2.2...4.2.3)

---
updated-dependencies:
- dependency-name: socket.io-parser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-27 11:41:03 +01:00
Jamie Peabody
2b561c1856 chore(doc): Update CDN example 2023-08-27 11:38:38 +01:00
18 changed files with 5208 additions and 4497 deletions

View File

@@ -1,3 +1,38 @@
## [5.1.2](https://github.com/wickedest/Mergely/compare/v5.1.1...v5.1.2) (2024-05-06)
### Bug Fixes
* trace only when debug enabled ([#194](https://github.com/wickedest/Mergely/issues/194)) ([60d18f8](https://github.com/wickedest/Mergely/commit/60d18f8d5c0df349b4806b2e8a6c0f79d9f8074e))
## [5.1.1](https://github.com/wickedest/Mergely/compare/v5.1.0...v5.1.1) (2024-03-11)
### Bug Fixes
* **#183:** fixes undefined 'k' due to scoped 'let' ([02e383d](https://github.com/wickedest/Mergely/commit/02e383d94d685e41cb68d945b9726bbcbfeb0ccf))
# [5.1.0](https://github.com/wickedest/Mergely/compare/v5.0.4...v5.1.0) (2023-08-27)
### Features
* support CM modes: go, javascript, htmlmixed, markdown, python ([827487a](https://github.com/wickedest/Mergely/commit/827487a5983cb89ef41415435d44239e35983b9a))
## [5.0.4](https://github.com/wickedest/Mergely/compare/v5.0.3...v5.0.4) (2023-08-27)
### Bug Fixes
* updated CDN example ([dec1e95](https://github.com/wickedest/Mergely/commit/dec1e9509d94811914e77cbc33dc1aaedf154f7c))
## [5.0.3](https://github.com/wickedest/Mergely/compare/v5.0.2...v5.0.3) (2023-08-27)
### Bug Fixes
* Updated docs with CDN example ([254adf1](https://github.com/wickedest/Mergely/commit/254adf15ab09fe9c5c3dff542d0a7f62ce2c9782))
## [5.0.2](https://github.com/wickedest/Mergely/compare/v5.0.1...v5.0.2) (2023-04-24)

View File

@@ -4,7 +4,7 @@
https://mergely.com
Mergely 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, for example, .txt, .html, .xml, .c, .cpp, .java, etc.
Mergely 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.
Mergely has a JavaScript implementation of the Longest Common Subsequence (LCS) diff algorithm, and a customizable markup engine. It computes the diff within the browser.
@@ -36,11 +36,11 @@ rm -rf .git
### Usage via CDN
Unpack mergely.tgz into a folder, for example, `./lib`, and add the following to the `<head>` of your target HTML source file.
Add the following to the `<head>` of your target HTML source file. Note that `codemirror` is bundled.
```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/mergely/5.0.0/mergely.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mergely/5.0.0/mergely.css"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mergely/5.0.0/mergely.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mergely/5.0.0/mergely.css" />
```
### Synchronous initialization
@@ -82,6 +82,16 @@ Mergely will emit an `updated` event when the editor is first initialized, and e
</body>
```
### Visualization modes
Mergely supports the following CodeMirror visualizations for [mode](codemirror.net/5/doc/manual.html#option_mode):
* go
* javascript
* htmlmixed
* markdown
* python
## Options
|Option|Type|Default value|Description|
@@ -93,8 +103,7 @@ Mergely will emit an `updated` event when the editor is first initialized, and e
|<a name="ignorews"></a>ignorews|boolean|`false`|Ignores white-space.|
|<a name="ignorecase"></a>ignorecase|boolean|`false`|Ignores case.|
|<a name="ignoreaccents"></a>ignoreaccents|boolean|`false`|Ignores accented characters.|
|<a name="inline"></a>inline|string|`chars`|The line-by-line (inline) type of diff. Valid values are: `none`, `chars`, `words`. When `none`, inline diff is disabled. When `chars` differientiation is done on a character-by-character basis. When `words` differentiation is done on a whitespace basis.|
|<a name="lcs"></a>lcs|boolean|`true`|:warning: **Deprecated**, use [`inline`](#inline). Enables/disables LCS computation for paragraphs (char-by-char changes). Disabling can give a performance gain for large documents.|
|<a name="lcs"></a>lcs|boolean|`true`|Enables/disables LCS computation for paragraphs (char-by-char changes). Disabling can give a performance gain for large documents.|
|<a name="lhs"></a>lhs|boolean,`function handler(setValue)`|`null`|Sets the value of the editor on the left-hand side.|
|<a name="license"></a>license|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).|
|<a name="line_numbers"></a>line_numbers|boolean|`true`|Enables/disables line numbers. Enabling line numbers will toggle the visibility of the line number margins.|

View File

@@ -4,9 +4,15 @@ require('codemirror/addon/selection/mark-selection.js');
require('codemirror/lib/codemirror.css');
require('../src/mergely.css');
const lhs = `hello`;
const lhs = `\
the quick red fox
jumped over the hairy dog
`;
const rhs = `hello\ngoodbye`;
const rhs = `\
the quick brown fox
jumped over the lazy dog
`;
document.onreadystatechange = function () {
@@ -16,7 +22,6 @@ document.onreadystatechange = function () {
const mergely = new Mergely('#compare', {
license: 'lgpl',
inline: 'words',
lhs,
rhs
});

38
examples/cdn.html Normal file
View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Mergely - Example full page editor</title>
<meta http-equiv="X-UA-Compatible" content="chrome=1, IE=edge">
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<meta name="description" content="" />
<meta name="keywords" content="mergely,diff,merge,compare" />
<meta name="author" content="Jamie Peabody" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<!-- Mergely -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mergely/5.0.0/mergely.min.js"></script>
<link type="text/css" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mergely/5.0.0/mergely.css" />
<style type="text/css">
html, body {
height: 100%;
margin: 0;
}
#compare {
height: inherit;
}
</style>
</head>
<body>
<div id="compare"></div>
<script>
const mergely = new Mergely('#compare');
mergely.once('updated', () => {
mergely.lhs('the quick red fox\njumped over the hairy dog');
mergely.rhs('the quick brown fox\njumped over the lazy dog');
});
</script>
</body>
</html>

View File

@@ -304,6 +304,7 @@ dog
and the postman
`
}];
console.log(data.length);
for (let i = 0; i < data.length; ++i) {
const { lhs, rhs } = data[i];
const darkModeOptions = i === 11 ? {

View File

@@ -298,6 +298,7 @@
rhs.style = 'color:initial';
});
jQuery('#search-text').on('keypress', (ev) => {
console.log(ev.which)
if (event.which === 13) {
ev.preventDefault();
jQuery('#search').click();

View File

@@ -21,6 +21,9 @@ This example demonstrates the minimum amount of code required to use Mergely.
<h1>Examples</h1>
<dl>
<dt><a href="cdn.html">cdn.html</a></dt>
<dd>Demonstrates how to use Mergely with CDN.</dd>
<dt><a href="editor.html">editor.html</a></dt>
<dd>An example editor showcasing some of Mergely's API features.</dd>

View File

@@ -22,6 +22,7 @@
"changelog" : {
"commitTypes": [
"docs",
"feat",
"fix",
"perf",

9067
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "mergely",
"version": "5.0.2",
"version": "5.1.2",
"description": "A javascript UI for diff/merge",
"license": "(GPL-3.0 OR LGPL-3.0 OR MPL-1.1 OR SEE LICENSE IN LICENSE)",
"author": {
@@ -57,7 +57,7 @@
"karma-sourcemap-loader": "^0.4.0",
"karma-webpack": "^5.0.0",
"mocha": "^9.1.4",
"semantic-release": "^21.0.1",
"semantic-release": "^21.1.2",
"simple-mock": "^0.8.0",
"standard-version": "^9.3.2",
"style-loader": "^3.3.1",

View File

@@ -2,6 +2,12 @@ const CodeMirror = require('codemirror');
require('codemirror/addon/search/searchcursor.js');
require('codemirror/addon/selection/mark-selection.js');
require('codemirror/lib/codemirror.css');
require('codemirror/mode/go/go.js');
require('codemirror/mode/javascript/javascript.js');
require('codemirror/mode/htmlmixed/htmlmixed.js');
require('codemirror/mode/markdown/markdown.js');
require('codemirror/mode/python/python.js');
const dom = require('./dom.js');
const VDoc = require('./vdoc');
@@ -52,9 +58,7 @@ CodeMirrorDiffView.prototype.unbind = function() {
if (this._unbound) {
return;
}
if (this.settings._debug) {
trace('api#unbind');
}
this.trace('api#unbind');
if (this._changedTimeout != null) {
clearTimeout(this._changedTimeout);
}
@@ -83,9 +87,7 @@ CodeMirrorDiffView.prototype.readOnly = function(side) {
}
CodeMirrorDiffView.prototype.lhs = function(text) {
if (this.settings._debug) {
trace('api#lhs', text && text.length);
}
this.trace('api#lhs', text && text.length);
// invalidate existing changes and current position
this.changes = [];
this._current_diff = -1;
@@ -94,33 +96,25 @@ CodeMirrorDiffView.prototype.lhs = function(text) {
CodeMirrorDiffView.prototype.rhs = function(text) {
// invalidate existing changes and current position
if (this.settings._debug) {
trace('api#rhs', text && text.length);
}
this.trace('api#rhs', text && text.length);
this.changes = [];
this._current_diff = -1;
this.editor.rhs.setValue(text);
};
CodeMirrorDiffView.prototype.update = function() {
if (this.settings._debug) {
trace('api#update');
}
this.trace('api#update');
this.el.dispatchEvent(new Event('changed'));
};
CodeMirrorDiffView.prototype.unmarkup = function() {
if (this.settings._debug) {
trace('api#unmarkup');
}
this.trace('api#unmarkup');
this._clear();
this.el.dispatchEvent(new Event('updated'));
};
CodeMirrorDiffView.prototype.scrollToDiff = function(direction) {
if (this.settings._debug) {
trace('api#scrollToDiff', direction);
}
this.trace('api#scrollToDiff', direction);
if (!this.changes.length) return;
if (direction === 'next') {
if (this._current_diff === this.changes.length - 1
@@ -137,18 +131,14 @@ CodeMirrorDiffView.prototype.scrollToDiff = function(direction) {
this._current_diff = Math.max(--this._current_diff, 0);
}
}
if (this.settings._debug) {
trace('change', 'current-diff', this._current_diff);
}
this.trace('change', 'current-diff', this._current_diff);
// _current_diff changed, refresh the view
this._scroll_to_change(this.changes[this._current_diff]);
this.setChanges(this.changes);
};
CodeMirrorDiffView.prototype.mergeCurrentChange = function(side) {
if (this.settings._debug) {
trace('api#mergeCurrentChange', side);
}
this.trace('api#mergeCurrentChange', side);
if (!this.changes.length) return;
if (side == 'lhs' && !this.lhs_cmsettings.readOnly) {
this._merge_change(this.changes[this._current_diff], 'rhs', 'lhs');
@@ -159,9 +149,7 @@ CodeMirrorDiffView.prototype.mergeCurrentChange = function(side) {
};
CodeMirrorDiffView.prototype.scrollTo = function(side, num) {
if (this.settings._debug) {
trace('api#scrollTo', side, num);
}
this.trace('api#scrollTo', side, num);
const ed = this.editor[side];
ed.setCursor(num);
ed.centerOnCursor();
@@ -175,9 +163,7 @@ CodeMirrorDiffView.prototype.setOptions = function(opts) {
...this.settings,
...opts
};
if (this.settings._debug) {
trace('api#setOptions', opts);
}
this.trace('api#setOptions', opts);
// if options set after init
if (this.editor) {
@@ -210,9 +196,7 @@ CodeMirrorDiffView.prototype.setOptions = function(opts) {
};
CodeMirrorDiffView.prototype.get = function(side) {
if (this.settings._debug) {
trace('api#get', side);
}
this.trace('api#get', side);
const ed = this.editor[side];
const value = ed.getValue();
if (value === undefined) {
@@ -222,16 +206,12 @@ CodeMirrorDiffView.prototype.get = function(side) {
};
CodeMirrorDiffView.prototype.cm = function(side) {
if (this.settings._debug) {
trace('api#cm', 'side');
}
this.trace('api#cm', 'side');
return this.editor[side];
};
CodeMirrorDiffView.prototype.search = function(side, query, direction) {
if (this.settings._debug) {
trace('api#search', side, query, direction);
}
this.trace('api#search', side, query, direction);
const editor = this.editor[side];
if (!editor.getSearchCursor) {
throw new Error('install CodeMirror search addon');
@@ -258,9 +238,7 @@ CodeMirrorDiffView.prototype.search = function(side, query, direction) {
};
CodeMirrorDiffView.prototype.resize = function() {
if (this.settings._debug) {
trace('api#resize');
}
this.trace('api#resize');
const parent = this.el;
const contentHeight = parent.offsetHeight - 2;
@@ -283,9 +261,7 @@ CodeMirrorDiffView.prototype.resize = function() {
};
CodeMirrorDiffView.prototype.bind = function(container) {
if (this.settings._debug) {
trace('api#bind', container);
}
this.trace('api#bind', container);
this._origEl = {
style: container.style,
className: container.className
@@ -407,9 +383,7 @@ CodeMirrorDiffView.prototype.bind = function(container) {
}
});
this.editor.rhs.on('beforeChange', (cm, ev) => {
if (this.settings._debug) {
trace('event#rhs-beforeChange', ev);
}
this.trace('event#rhs-beforeChange', ev);
if (ev.text.length > 1
|| ((ev.from.line - ev.to.line) && ev.origin === '+delete')) {
this._clear();
@@ -417,24 +391,16 @@ CodeMirrorDiffView.prototype.bind = function(container) {
});
this.editor.lhs.on('change', (instance, ev) => {
if (this.settings._debug) {
trace('event#lhs-change');
}
this.trace('event#lhs-change');
this._changing();
if (this.settings._debug) {
trace('event#lhs-change [emitted]');
}
this.trace('event#lhs-change [emitted]');
});
this.editor.lhs.on('scroll', () => {
if (this._skipscroll.lhs) {
if (this.settings._debug) {
trace('event#lhs-scroll (skipped)');
}
this.trace('event#lhs-scroll (skipped)');
return;
} else {
if (this.settings._debug) {
trace('event#lhs-scroll');
}
this.trace('event#lhs-scroll');
}
// firefox scroll-linked effect render issue
setTimeout(() => {
@@ -442,21 +408,15 @@ CodeMirrorDiffView.prototype.bind = function(container) {
}, 1);
});
this.editor.rhs.on('change', (instance, ev) => {
if (this.settings._debug) {
trace('event#rhs-change', ev);
}
this.trace('event#rhs-change', ev);
this._changing();
});
this.editor.rhs.on('scroll', () => {
if (this._skipscroll.rhs) {
if (this.settings._debug) {
trace('event#rhs-scroll (skipped)');
}
this.trace('event#rhs-scroll (skipped)');
return;
} else {
if (this.settings._debug) {
trace('event#rhs-scroll');
}
this.trace('event#rhs-scroll');
}
// firefox scroll-linked effect render issue
setTimeout(() => {
@@ -469,7 +429,7 @@ CodeMirrorDiffView.prototype.bind = function(container) {
const resize = () => {
if (this.settings._debug) {
traceTimeStart('event#resize');
trace('event#resize [start]');
this.trace('event#resize [start]');
}
this.resize();
if (this.settings._debug) {
@@ -526,16 +486,12 @@ CodeMirrorDiffView.prototype.bind = function(container) {
}
this.editor.lhs.on('gutterClick', (cm, n, gutterClass, ev) => {
if (this.settings._debug) {
trace('event#gutterClick', 'lhs', n, ev);
}
this.trace('event#gutterClick', 'lhs', n, ev);
gutterClicked.call(this, 'lhs', n, ev);
});
this.editor.rhs.on('gutterClick', (cm, n, gutterClass, ev) => {
if (this.settings._debug) {
trace('event#gutterClick', 'rhs', n, ev);
}
this.trace('event#gutterClick', 'rhs', n, ev);
gutterClicked.call(this, 'rhs', n, ev);
});
@@ -683,18 +639,14 @@ CodeMirrorDiffView.prototype._scrolling = function({ side }) {
const vp = this.editor[oside].getViewport();
let scroll = true;
if (last_change) {
if (this.settings._debug) {
trace('scroll#_scrolling', 'last change before midline', last_change);
}
this.trace('scroll#_scrolling', 'last change before midline', last_change);
if (midline.line >= vp.from && midline <= vp.to) {
scroll = false;
}
}
if (scroll || force_scroll) {
// scroll the other side
if (this.settings._debug) {
trace('scroll#_scrolling', 'other side', oside, 'pos:', top_to - top_adjust);
}
this.trace('scroll#_scrolling', 'other side', oside, 'pos:', top_to - top_adjust);
// disable linked scroll events for the opposite editor because this
// triggers the next one explicitly, and we don't want to link the
@@ -702,21 +654,21 @@ CodeMirrorDiffView.prototype._scrolling = function({ side }) {
// coming in 2s, so this will "link" scrolling the other editor to
// this editor until this editor stops scrolling and times out.
this._skipscroll[oside] = true;
trace('scroll#set oside skip set:', oside, this._skipscroll);
this.trace('scroll#set oside skip set:', oside, this._skipscroll);
if (this._linkedScrollTimeout[oside]) {
clearTimeout(this._linkedScrollTimeout[oside]);
trace('scroll#clearing timeout:', this._skipscroll);
this.trace('scroll#clearing timeout:', this._skipscroll);
}
this._linkedScrollTimeout[oside] = setTimeout(() => {
this._skipscroll[oside] = false;
trace('scroll#set oside skip unset:', oside, this._skipscroll);
this.trace('scroll#set oside skip unset:', oside, this._skipscroll);
}, 100);
const top = top_to - top_adjust;
// scroll the opposite editor
this.editor[oside].scrollTo(left_to, top);
} else if (this.settings._debug) {
trace('scroll#_scrolling', 'not scrolling other side');
} else {
this.trace('scroll#_scrolling', 'not scrolling other side');
}
this._renderChanges();
@@ -727,23 +679,19 @@ CodeMirrorDiffView.prototype._scrolling = function({ side }) {
CodeMirrorDiffView.prototype._changing = function() {
if (!this.settings.autoupdate) {
if (this.settings._debug) {
trace('change#_changing autoupdate is disabled');
}
this.trace('change#_changing autoupdate is disabled');
return;
}
if (this.settings._debug) {
traceTimeStart('change#_changing');
trace('change#_changing [start]');
this.trace('change#_changing [start]');
}
const handleChange = () => {
this._changedTimeout = null;
this.el.dispatchEvent(new Event('changed'));
};
if (this.settings.change_timeout > 0) {
if (this.settings._debug) {
trace('change#setting timeout', this.settings.change_timeout)
}
this.trace('change#setting timeout', this.settings.change_timeout)
if (this._changedTimeout != null) {
clearTimeout(this._changedTimeout);
}
@@ -757,9 +705,7 @@ CodeMirrorDiffView.prototype._changing = function() {
};
CodeMirrorDiffView.prototype.setChanges = function(changes) {
if (this.settings._debug) {
trace('change#setChanges');
}
this.trace('change#setChanges');
this._clear();
// after clear, set the new changes
this.changes = changes;
@@ -769,7 +715,7 @@ CodeMirrorDiffView.prototype.setChanges = function(changes) {
CodeMirrorDiffView.prototype._renderChanges = function() {
if (this.settings._debug) {
traceTimeStart('draw#_renderChanges');
trace('draw#_renderChanges [start]', this.changes.length, 'changes');
this.trace('draw#_renderChanges [start]', this.changes.length, 'changes');
}
this._clearCanvases();
this._calculateOffsets(this.changes);
@@ -941,6 +887,7 @@ CodeMirrorDiffView.prototype._markupLineChanges = function (changes) {
for (let i = 0; i < changes.length; ++i) {
const change = changes[i];
const isCurrent = current_diff === i;
const lineDiff = this.settings.lcs !== false;
const lhsInView = this._isChangeInView('lhs', lhsvp, change);
const rhsInView = this._isChangeInView('rhs', rhsvp, change);
@@ -951,7 +898,7 @@ CodeMirrorDiffView.prototype._markupLineChanges = function (changes) {
vdoc.addRender('lhs', change, i, {
isCurrent,
lineDiff: this.settings.inline !== 'none',
lineDiff,
// TODO: move out of loop
getMergeHandler: (change, side, oside) => {
return () => this._merge_change(change, side, oside);
@@ -968,7 +915,7 @@ CodeMirrorDiffView.prototype._markupLineChanges = function (changes) {
vdoc.addRender('rhs', change, i, {
isCurrent,
lineDiff: this.settings.inline !== 'none',
lineDiff,
// TODO: move out of loop
getMergeHandler: (change, side, oside) => {
return () => this._merge_change(change, side, oside);
@@ -978,14 +925,13 @@ CodeMirrorDiffView.prototype._markupLineChanges = function (changes) {
});
}
if (this.settings.inline !== 'none'
if (lineDiff
&& (lhsInView || rhsInView)
&& change.op === 'c') {
vdoc.addInlineDiff(change, i, {
ignoreaccents: this.settings.ignoreaccents,
ignorews: this.settings.ignorews,
ignorecase: this.settings.ignorecase,
split: this.settings.inline,
getText: (side, lineNum) => {
if (side === 'lhs') {
const text = led.getLine(lineNum);
@@ -1097,12 +1043,9 @@ CodeMirrorDiffView.prototype._renderDiff = function(changes) {
const ctx_lhs = mcanvas_lhs.getContext('2d');
const ctx_rhs = mcanvas_rhs.getContext('2d');
if (this.settings._debug
&& this.settings._debug) {
trace('draw#_renderDiff', 'visible page height', ex.visible_page_height);
trace('draw#_renderDiff', 'scroller-top lhs', ex.lhs_scroller.scrollTop);
trace('draw#_renderDiff', 'scroller-top rhs', ex.rhs_scroller.scrollTop);
}
this.trace('draw#_renderDiff', 'visible page height', ex.visible_page_height);
this.trace('draw#_renderDiff', 'scroller-top lhs', ex.lhs_scroller.scrollTop);
this.trace('draw#_renderDiff', 'scroller-top rhs', ex.rhs_scroller.scrollTop);
ex.lhs_margin.removeEventListener('click', this._handleLhsMarginClick);
ex.rhs_margin.removeEventListener('click', this._handleRhsMarginClick);
@@ -1127,17 +1070,16 @@ CodeMirrorDiffView.prototype._renderDiff = function(changes) {
const rhs_y_end = change['rhs-y-end'] - rhsScrollTop;
if (Number.isNaN(lhs_y_start)) {
trace('draw#_renderDiff', 'unexpected NaN',
change['lhs-y-start'], change['lhs-y-end']);
this.trace(
'draw#_renderDiff unexpected NaN',
change['lhs-y-start'], change['lhs-y-end']
);
continue;
}
// draw margin indicators
if (this.settings._debug
&& this.settings._debug) {
trace('draw#_renderDiff', 'draw1', 'marker',
lhs_y_start, lhs_y_end, rhs_y_start, rhs_y_end);
}
this.trace('draw#_renderDiff', 'draw1', 'marker',
lhs_y_start, lhs_y_end, rhs_y_start, rhs_y_end);
const mkr_lhs_y_start = change['lhs-y-start'] * lratio;
const mkr_lhs_y_end = Math.max(change['lhs-y-end'] * lratio, 5);
@@ -1266,4 +1208,10 @@ CodeMirrorDiffView.prototype._queryElement = function(selector) {
return this[cacheName];
}
CodeMirrorDiffView.prototype.trace = function(...args) {
if (this.settings._debug) {
console.log(...args);
}
}
module.exports = CodeMirrorDiffView;

View File

@@ -1,52 +1,43 @@
const Encoder = require('./encoder.js');
const SMS_TIMEOUT_SECONDS = 1.0;
function diff(lhs, rhs, opts) {
function diff(lhs, rhs, options = {}) {
const {
ignorews = false,
ignoreaccents = false,
ignorecase = false,
split = 'lines'
} = opts || {};
const options = {
} = options;
this.codeify = new CodeifyText(lhs, rhs, {
ignorews,
ignoreaccents,
ignorecase,
split
};
const encoder = new Encoder();
const lhsCodes = encoder.encode(lhs, options);
const rhsCodes = encoder.encode(rhs, options);
const lhsCtx = {
codes: lhsCodes.codes,
length: lhsCodes.length,
parts: lhsCodes.parts,
});
const lhs_ctx = {
codes: this.codeify.getCodes('lhs'),
modified: {}
};
const rhsCtx = {
codes: rhsCodes.codes,
length: rhsCodes.length,
parts: rhsCodes.parts,
const rhs_ctx = {
codes: this.codeify.getCodes('rhs'),
modified: {}
};
const vector_d = [];
const vector_u = [];
this._lcs(lhsCtx, 0, lhsCodes.length, rhsCtx, 0, rhsCodes.length, vector_u, vector_d);
this._optimize(lhsCtx);
this._optimize(rhsCtx);
this.items = this._create_diffs(lhsCtx, rhsCtx, options);
this.sides = {
lhs: lhsCtx,
rhs: rhsCtx
};
this._lcs(lhs_ctx, 0, lhs_ctx.codes.length, rhs_ctx, 0, rhs_ctx.codes.length, vector_u, vector_d);
this._optimize(lhs_ctx);
this._optimize(rhs_ctx);
this.items = this._create_diffs(lhs_ctx, rhs_ctx);
};
diff.prototype.changes = function() {
return this.items;
};
diff.prototype.getLines = function(side) {
return this.codeify.getLines(side);
};
diff.prototype.normal_form = function() {
let nf = '';
for (let index = 0; index < this.items.length; ++index) {
@@ -66,8 +57,8 @@ diff.prototype.normal_form = function() {
else rhs_str = (item.rhs_start + 1) + ',' + (item.rhs_start + item.rhs_inserted_count);
nf += lhs_str + change + rhs_str + '\n';
const lhs_lines = this.sides.lhs.parts;
const rhs_lines = this.sides.rhs.parts;
const lhs_lines = this.getLines('lhs');
const rhs_lines = this.getLines('rhs');
if (rhs_lines && lhs_lines) {
let i;
// if rhs/lhs lines have been retained, output contextual diff
@@ -111,7 +102,7 @@ diff.prototype._lcs = function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower
diff.prototype._sms = function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower, rhs_upper, vector_u, vector_d) {
const timeout = Date.now() + SMS_TIMEOUT_SECONDS * 1000;
const max = lhs_ctx.length + rhs_ctx.length + 1;
const max = lhs_ctx.codes.length + rhs_ctx.codes.length + 1;
const kdown = lhs_lower - rhs_lower;
const kup = lhs_upper - rhs_upper;
const delta = (lhs_upper - lhs_lower) - (rhs_upper - rhs_lower);
@@ -124,13 +115,12 @@ diff.prototype._sms = function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower
const ret = { x:0, y:0 }
let x;
let y;
let k;
for (let d = 0; d <= maxd; ++d) {
if (SMS_TIMEOUT_SECONDS && Date.now() > timeout) {
// bail if taking too long
return { x: lhs_lower, y: rhs_upper };
}
for (k = kdown - d; k <= kdown + d; k += 2) {
for (let k = kdown - d; k <= kdown + d; k += 2) {
if (k === kdown - d) {
x = vector_d[ offset_down + k + 1 ];//down
}
@@ -156,7 +146,7 @@ diff.prototype._sms = function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower
}
}
// Extend the reverse path.
for (k = kup - d; k <= kup + d; k += 2) {
for (let k = kup - d; k <= kup + d; k += 2) {
// find the only or better starting point
if (k === kup + d) {
x = vector_u[offset_up + k - 1]; // up
@@ -188,15 +178,15 @@ diff.prototype._sms = function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower
diff.prototype._optimize = function(ctx) {
let start = 0;
let end = 0;
while (start < ctx.length) {
while ((start < ctx.length) && (ctx.modified[start] === undefined || ctx.modified[start] === false)) {
while (start < ctx.codes.length) {
while ((start < ctx.codes.length) && (ctx.modified[start] === undefined || ctx.modified[start] === false)) {
start++;
}
end = start;
while ((end < ctx.length) && (ctx.modified[end] === true)) {
while ((end < ctx.codes.length) && (ctx.modified[end] === true)) {
end++;
}
if ((end < ctx.length) && (ctx.codes[start] === ctx.codes[end])) {
if ((end < ctx.codes.length) && (ctx.codes[start] === ctx.codes[end])) {
ctx.modified[start] = false;
ctx.modified[end] = true;
}
@@ -206,16 +196,16 @@ diff.prototype._optimize = function(ctx) {
}
};
diff.prototype._create_diffs = function(lhs_ctx, rhs_ctx, options) {
diff.prototype._create_diffs = function(lhs_ctx, rhs_ctx) {
const items = [];
let lhs_start = 0;
let rhs_start = 0;
let lhs_line = 0;
let rhs_line = 0;
while (lhs_line < lhs_ctx.length || rhs_line < rhs_ctx.length) {
if ((lhs_line < lhs_ctx.length) && (!lhs_ctx.modified[lhs_line])
&& (rhs_line < rhs_ctx.length) && (!rhs_ctx.modified[rhs_line])) {
while (lhs_line < lhs_ctx.codes.length || rhs_line < rhs_ctx.codes.length) {
if ((lhs_line < lhs_ctx.codes.length) && (!lhs_ctx.modified[lhs_line])
&& (rhs_line < rhs_ctx.codes.length) && (!rhs_ctx.modified[rhs_line])) {
// equal lines
lhs_line++;
rhs_line++;
@@ -225,50 +215,19 @@ diff.prototype._create_diffs = function(lhs_ctx, rhs_ctx, options) {
lhs_start = lhs_line;
rhs_start = rhs_line;
while (lhs_line < lhs_ctx.length && (rhs_line >= rhs_ctx.length || lhs_ctx.modified[lhs_line]))
while (lhs_line < lhs_ctx.codes.length && (rhs_line >= rhs_ctx.codes.length || lhs_ctx.modified[lhs_line]))
lhs_line++;
while (rhs_line < rhs_ctx.length && (lhs_line >= lhs_ctx.length || rhs_ctx.modified[rhs_line]))
while (rhs_line < rhs_ctx.codes.length && (lhs_line >= lhs_ctx.codes.length || rhs_ctx.modified[rhs_line]))
rhs_line++;
if ((lhs_start < lhs_line) || (rhs_start < rhs_line)) {
// store a new difference-item
let deleted_count;
let inserted_count;
let lhs_start = lhs_line;
let rhs_start = rhs_line;
if (options.split === 'lines') {
lhs_start = lhs_line;
rhs_start = rhs_line;
deleted_count = lhs_line - lhs_start;
inserted_count = rhs_line - rhs_start;
} else {
const ditem_lhs_start = (lhs_start >= lhs_ctx.length)
? lhs_ctx.length
: lhs_ctx.parts[lhs_start].from;
const ditem_rhs_start = (rhs_start >= rhs_ctx.length)
? rhs_ctx.length
: rhs_ctx.parts[rhs_start].from;
const ditem_lhs_end = (lhs_line >= lhs_ctx.length)
? lhs_ctx.length
: lhs_ctx.parts[lhs_line].from;
const ditem_rhs_end = (rhs_line >= rhs_ctx.length)
? rhs_ctx.length
: rhs_ctx.parts[rhs_line];
// const delim_len = (options.split === 'words') ? 1 : 0;
// const ditemLhs
deleted_count = ditem_lhs_end - ditem_lhs_start;
inserted_count = ditem_rhs_end - ditem_rhs_start;
lhs_start = ditem_lhs_start;
rhs_start = ditem_rhs_start;
}
items.push({
lhs_start: lhs_start,
rhs_start: rhs_start,
lhs_deleted_count: deleted_count,
rhs_inserted_count: inserted_count
lhs_deleted_count: lhs_line - lhs_start,
rhs_inserted_count: rhs_line - rhs_start
});
}
}
@@ -276,4 +235,77 @@ diff.prototype._create_diffs = function(lhs_ctx, rhs_ctx, options) {
return items;
};
function CodeifyText(lhs, rhs, options) {
this._max_code = 0;
this._diff_codes = {};
this.ctxs = {};
this.options = options;
this.options.split = this.options.split || 'lines';
if (typeof lhs === 'string') {
if (this.options.split === 'chars') {
this.lhs = lhs.split('');
} else if (this.options.split === 'words') {
this.lhs = lhs.split(/\s/);
} else if (this.options.split === 'lines') {
this.lhs = lhs.split('\n');
}
} else {
this.lhs = lhs;
}
if (typeof rhs === 'string') {
if (this.options.split === 'chars') {
this.rhs = rhs.split('');
} else if (this.options.split === 'words') {
this.rhs = rhs.split(/\s/);
} else if (this.options.split === 'lines') {
this.rhs = rhs.split('\n');
}
} else {
this.rhs = rhs;
}
};
CodeifyText.prototype.getCodes = function(side) {
if (!this.ctxs.hasOwnProperty(side)) {
var ctx = this._diff_ctx(this[side]);
this.ctxs[side] = ctx;
ctx.codes.length = Object.keys(ctx.codes).length;
}
return this.ctxs[side].codes;
}
CodeifyText.prototype.getLines = function(side) {
return this.ctxs[side].lines;
}
CodeifyText.prototype._diff_ctx = function(lines) {
var ctx = {i: 0, codes: {}, lines: lines};
this._codeify(lines, ctx);
return ctx;
}
CodeifyText.prototype._codeify = function(lines, ctx) {
for (let i = 0; i < lines.length; ++i) {
let line = lines[i];
if (this.options.ignorews) {
line = line.replace(/\s+/g, '');
}
if (this.options.ignorecase) {
line = line.toLowerCase();
}
if (this.options.ignoreaccents) {
line = line.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
const aCode = this._diff_codes[line];
if (aCode !== undefined) {
ctx.codes[i] = aCode;
} else {
++this._max_code;
this._diff_codes[line] = this._max_code;
ctx.codes[i] = this._max_code;
}
}
}
module.exports = diff;

View File

@@ -1,79 +0,0 @@
class Encoder {
constructor() {
this._maxCode = 0;
this._codes = {};
}
encode(text, options) {
let exp;
let fudge = 0;
if (options.split === 'chars') {
exp = /./g;
fudge = 1;
} else if (options.split === 'words') {
exp = /\s+/g;
} else {
exp = /\n/g;
}
let match;
let p0 = -1;
const parts = [];
while ((match = exp.exec(text)) !== null) {
const from = (options.split === 'lines') ? parts.length : p0 + 1;
const to = (options.split === 'lines') ? parts.length + 1 : match.index + fudge;
const item = {
from,
to,
text: text.substr(p0 + 1, match.index - p0 - 1 + fudge)
};
parts.push(item);
p0 = match.index;
}
const from = (options.split === 'lines') ? parts.length : p0 + 1;
const to = (options.split === 'lines') ? parts.length + 1 : text.length;
parts.push({
from,
to,
text: text.substr(p0 + 1)
});
const hash = this._hash(parts, options)
return {
codes: hash.codes,
parts: hash.parts,
length: Object.keys(hash.codes).length
};
}
_hash(parts, options) {
const codes = {};
let i = 0;
for (const part of parts) {
let text = part.text;
if (options.ignorews) {
text = text.replace(/\s+/g, '');
}
if (options.ignorecase) {
text = text.toLowerCase();
}
if (options.ignoreaccents) {
text = text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
const code = this._codes[text];
if (code !== undefined) {
codes[i] = code;
} else {
++this._maxCode;
this._codes[text] = this._maxCode;
codes[i] = this._maxCode;
}
i += 1;
}
return {
codes,
parts
};
}
}
module.exports = Encoder;

View File

@@ -12,7 +12,6 @@ const defaultOptions = {
wrap_lines: false,
line_numbers: true,
lcs: true,
inline: 'chars',
sidebar: true,
viewport: false,
ignorews: false,
@@ -24,7 +23,8 @@ const defaultOptions = {
vpcolor: 'rgba(0, 0, 200, 0.5)',
license: 'lgpl',
cmsettings: {
styleSelectedText: true
styleSelectedText: true,
mode: null
},
lhs_cmsettings: {},
rhs_cmsettings: {},
@@ -120,15 +120,13 @@ class Mergely {
const colors = dom.getColors(this.el);
this._options = {
...defaultOptions,//lgpl
...{
// default inline based off `lcs`
inline: options && options.lcs === false ? 'none' : 'chars'
},
...this._initOptions,
...options,//lgpl-separate-notice
...options//lgpl-separate-notice
};
this._viewOptions = {
...this._options,
...defaultOptions,
...this._initOptions,
...options,
_colors: colors
};
}

View File

@@ -124,7 +124,7 @@ class VDoc {
this._setRenderedChange(side, changeId);
}
addInlineDiff(change, changeId, { getText, ignorews, ignoreaccents, ignorecase, split = 'chars' }) {
addInlineDiff(change, changeId, { getText, ignorews, ignoreaccents, ignorecase }) {
if (this.options._debug) {
trace('vdoc#addInlineDiff', changeId, change);
}
@@ -152,7 +152,7 @@ class VDoc {
ignoreaccents,
ignorews,
ignorecase,
split
split: 'chars'
});
for (const change of results.changes()) {
const {

View File

@@ -1,16 +0,0 @@
const diff = require('../src/diff');
describe('diff', () => {
it('should insert one line when lhs is empty and rhs has no line ending', () => {
const _diff = new diff('', 'hello', { split: 'lines' });
const changes = _diff.changes();
console.log(changes);
// with lhs_start at 1, the insert is at the end
expect(changes).to.deep.equal([{
lhs_start: 1,
rhs_start: 1,
lhs_deleted_count: 0,
rhs_inserted_count: 0
}]);
});
});

View File

@@ -189,6 +189,7 @@ describe('markup', () => {
expect(editor.querySelectorAll('.mergely.rhs')).to.have.length(0);
}
},
{
name: 'Changed lines (lhs)',
lhs: 'the quick red fox\njumped over the hairy dog',
@@ -232,46 +233,6 @@ describe('markup', () => {
expect(rhs_spans[1].innerText).to.equal('h');
expect(rhs_spans[2].innerText).to.equal('ir');
}
},
{
name: 'Changed lines with inline words (lhs)',
lhs: 'the quick red fox\njumped over the hairy dog',
rhs: 'the quick brown fox\njumped over the lazy dog',
options: { inline: 'words' },
check: (editor) => {
expect(editor.querySelectorAll(LHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_CHANGE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_END + '.cid-0')).to.have.length(1);
const lhs_spans = editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0');
expect(lhs_spans).to.have.length(2);
expect(lhs_spans[0].innerText).to.equal('red');
expect(lhs_spans[1].innerText).to.equal('hairy');
const rhs_spans = editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0');
expect(rhs_spans).to.have.length(2);
expect(rhs_spans[0].innerText).to.equal('brown');
expect(rhs_spans[1].innerText).to.equal('lazy');
}
},
{
name: 'Changed lines (rhs)',
lhs: 'the quick brown fox\njumped over the lazy dog',
rhs: 'the quick red fox\njumped over the hairy dog',
options: { inline: 'words' },
check: (editor) => {
expect(editor.querySelectorAll(LHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(LHS_CHANGE_END + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_START + '.cid-0')).to.have.length(1);
expect(editor.querySelectorAll(RHS_CHANGE_END + '.cid-0')).to.have.length(1);
const lhs_spans = editor.querySelectorAll(LHS_INLINE_TEXT + '.cid-0');
expect(lhs_spans).to.have.length(2);
expect(lhs_spans[0].innerText).to.equal('brown');
expect(lhs_spans[1].innerText).to.equal('lazy');
const rhs_spans = editor.querySelectorAll(RHS_INLINE_TEXT + '.cid-0');
expect(rhs_spans).to.have.length(2);
expect(rhs_spans[0].innerText).to.equal('red');
expect(rhs_spans[1].innerText).to.equal('hairy');
}
}
];
@@ -285,9 +246,8 @@ describe('markup', () => {
license: 'lgpl-separate-notice',
change_timeout: 0,
_debug: debug,
lhs: opt.lhs,
rhs: opt.rhs,
...opt.options
lhs: (setValue) => setValue(opt.lhs),
rhs: (setValue) => setValue(opt.rhs)
});
const test = () => {
try {

View File

@@ -8,7 +8,6 @@ const defaultOptions = {
rhs_margin: 'right',
wrap_lines: false,
line_numbers: true,
inline: 'chars',
lcs: true,
sidebar: true,
viewport: false,
@@ -23,7 +22,8 @@ const defaultOptions = {
vpcolor: 'rgba(0, 0, 200, 0.5)',
license: 'lgpl',
cmsettings: {
styleSelectedText: true
styleSelectedText: true,
mode: null
},
_debug: false
};