Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9f2edc1ad | ||
|
|
3d44470103 | ||
|
|
2c8f6cd340 | ||
|
|
6716096215 | ||
|
|
217674cd07 | ||
|
|
3812dd6026 | ||
|
|
ead86867c4 |
19
.babelrc.js
Normal file
19
.babelrc.js
Normal file
@@ -0,0 +1,19 @@
|
||||
module.exports = function(api) {
|
||||
return {
|
||||
presets: [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
targets: {
|
||||
chrome: 59,
|
||||
edge: 13,
|
||||
firefox: 50,
|
||||
ie: 11
|
||||
},
|
||||
// for uglifyjs...
|
||||
forceAllTransforms: api.env("production"),
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
};
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
/node_modules
|
||||
/lib
|
||||
mergely-*.tgz
|
||||
package-lock.json
|
||||
*.log
|
||||
|
||||
18
CHANGES.md
18
CHANGES.md
@@ -1,5 +1,23 @@
|
||||
# Changes
|
||||
|
||||
## 4.0.8
|
||||
* chore: updated webpack
|
||||
|
||||
## 4.0.7
|
||||
* chore: updated documentation
|
||||
|
||||
## 4.0.6
|
||||
|
||||
* #89: fixes missing merge buttons
|
||||
|
||||
## 4.0.5
|
||||
|
||||
* #85: fixes XSS vulnerability with DOM id
|
||||
|
||||
## 4.0.2
|
||||
|
||||
* #83: fixes poor rendering performance
|
||||
|
||||
## 4.0.0
|
||||
|
||||
### Breaking changes
|
||||
|
||||
@@ -9,6 +9,9 @@ Mergely is a javascript component to diff/merge files interactively in a browser
|
||||
### Installation via webpack
|
||||
The recommended way to install mergely is to use npm and [webpack](https://webpack.js.org/) to install mergely and its dependencies. It is highly recommended that you start by cloning [mergely-webpack](https://github.com/wickedest/mergely-webpack). It has everything that you need to get started.
|
||||
|
||||
### Angular 6.1.1
|
||||
You can also use mergely within angular. You can start by cloning [mergely-angular](https://github.com/wickedest/mergely-angular).
|
||||
|
||||
### Installation via .tgz
|
||||
|
||||
Unpack mergely.tgz into a folder, e.g. `./lib`, and then add the following to the `<head>` of your target html source file.
|
||||
@@ -46,9 +49,6 @@ The following example can be used to set the `lhs` and `rhs` editors synchronous
|
||||
|
||||
```js
|
||||
$(document).ready(function () {
|
||||
// initialize mergely
|
||||
$('#mergely').mergely();
|
||||
|
||||
// set editor content
|
||||
$('#mergely').mergely({
|
||||
lhs: function(setValue) {
|
||||
|
||||
21
examples/app.html
Normal file
21
examples/app.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!--
|
||||
This example demonstrates the minimum amount of code required to use Mergely.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" /><title>Mergely - Simple Example</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="Merge and Diff your documents with diff online and share" />
|
||||
<meta name="keywords" content="diff,merge,compare,jsdiff,comparison,difference,file,text,unix,patch,algorithm,saas,longest common subsequence" />
|
||||
<meta name="author" content="Jamie Peabody" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="mergely-full-screen-8">
|
||||
<div class="mergely-resizer">
|
||||
<div id="mergely"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
18
examples/app.js
Normal file
18
examples/app.js
Normal file
@@ -0,0 +1,18 @@
|
||||
require('codemirror/lib/codemirror.css');
|
||||
require('../src/mergely.css');
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#mergely').mergely({
|
||||
license: 'lgpl',
|
||||
cmsettings: {
|
||||
readOnly: false
|
||||
},
|
||||
_debug: '',
|
||||
lhs: function(setValue) {
|
||||
setValue('the quick red fox\njumped over the hairy dog');
|
||||
},
|
||||
rhs: function(setValue) {
|
||||
setValue('the quick brown fox\njumped over the lazy dog');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,5 @@
|
||||
const path = require('path');
|
||||
const webpackCfg = require('./webpack.config');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
@@ -40,9 +39,11 @@ module.exports = function(config) {
|
||||
webpack: {
|
||||
entry: './src/mergely.js',
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('css-loader') }
|
||||
]
|
||||
rules: [{
|
||||
test: /\.(js)$/,
|
||||
exclude: /node_modules/,
|
||||
use: ['babel-loader']
|
||||
}]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js'],
|
||||
@@ -52,7 +53,11 @@ module.exports = function(config) {
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new ExtractTextPlugin('mergely.css')
|
||||
new CopyWebpackPlugin([{
|
||||
from: 'src/mergely.css',
|
||||
to: 'mergely.css',
|
||||
toType: 'file'
|
||||
}])
|
||||
]
|
||||
},
|
||||
webpackServer: {
|
||||
|
||||
34
package.json
34
package.json
@@ -1,17 +1,12 @@
|
||||
{
|
||||
"name": "mergely",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.8",
|
||||
"description": "A javascript UI for diff/merge",
|
||||
"directories": {
|
||||
"doc": "doc",
|
||||
"example": "examples",
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rm -rf lib && webpack",
|
||||
"test": "karma start",
|
||||
"test:chrome": "karma start --browsers Chrome --singleRun=false"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/wickedest/Mergely.git"
|
||||
@@ -20,7 +15,8 @@
|
||||
"files": [
|
||||
"lib",
|
||||
"examples",
|
||||
"README.md"
|
||||
"README.md",
|
||||
"LICENSE"
|
||||
],
|
||||
"keywords": [
|
||||
"merge",
|
||||
@@ -38,14 +34,20 @@
|
||||
},
|
||||
"homepage": "https://github.com/wickedest/Mergely#readme",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.1.6",
|
||||
"@babel/preset-env": "^7.1.6",
|
||||
"@webpack-cli/init": "^0.1.2",
|
||||
"babel-loader": "^8.0.4",
|
||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||
"chai": "^4.1.2",
|
||||
"codemirror": "^5.32.0",
|
||||
"css-loader": "^0.28.7",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"copy-webpack-plugin": "^4.6.0",
|
||||
"css-loader": "^0.28.11",
|
||||
"file-loader": "^1.1.5",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"image-webpack-loader": "^3.4.2",
|
||||
"jquery": "^3.2.1",
|
||||
"karma": "^2.0.0",
|
||||
"karma": "^3.1.1",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-coverage-istanbul-reporter": "^1.3.0",
|
||||
@@ -53,6 +55,16 @@
|
||||
"karma-mocha-reporter": "^2.2.5",
|
||||
"karma-webpack": "^2.0.9",
|
||||
"mocha": "^4.0.1",
|
||||
"webpack": "^3.8.1"
|
||||
"style-loader": "^0.23.0",
|
||||
"uglifyjs-webpack-plugin": "^2.0.1",
|
||||
"webpack": "^4.20.2",
|
||||
"webpack-cli": "^3.1.2",
|
||||
"webpack-dev-server": "^3.1.9"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rm -rf lib && webpack --config ./webpack.prod.js",
|
||||
"start": "webpack-dev-server -w --debug --progress --colors --config ./webpack.dev.js --content-base ./dist --inline --hot --host 0.0.0.0",
|
||||
"test": "karma start",
|
||||
"test:chrome": "karma start --browsers Chrome --singleRun=false"
|
||||
}
|
||||
}
|
||||
|
||||
16
src/Timer.js
Normal file
16
src/Timer.js
Normal file
@@ -0,0 +1,16 @@
|
||||
class Timer {
|
||||
static start() {
|
||||
Timer.t0 = Date.now();
|
||||
}
|
||||
|
||||
static stop() {
|
||||
var t1 = Date.now();
|
||||
var td = t1 - Timer.t0;
|
||||
Timer.t0 = t1;
|
||||
return td;
|
||||
}
|
||||
}
|
||||
|
||||
Timer.t0 = 0;
|
||||
|
||||
exports = module.exports = Timer;
|
||||
280
src/mergely.js
280
src/mergely.js
@@ -1,25 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
require('./mergely.css');
|
||||
|
||||
(function(jQuery, CodeMirror) {
|
||||
|
||||
var Mgly = {};
|
||||
|
||||
Mgly.Timer = function(){
|
||||
var self = this;
|
||||
self.start = function() { self.t0 = new Date().getTime(); };
|
||||
self.stop = function() {
|
||||
var t1 = new Date().getTime();
|
||||
var d = t1 - self.t0;
|
||||
self.t0 = t1;
|
||||
return d;
|
||||
};
|
||||
self.start();
|
||||
};
|
||||
|
||||
Mgly.ChangeExpression = new RegExp(/(^(?![><\-])*\d+(?:,\d+)?)([acd])(\d+(?:,\d+)?)/);
|
||||
|
||||
const Timer = require('./Timer');
|
||||
|
||||
Mgly.DiffParser = function(diff) {
|
||||
var changes = [];
|
||||
var change_id = 0;
|
||||
@@ -54,8 +42,8 @@ Mgly.sizeOf = function(obj) {
|
||||
};
|
||||
|
||||
Mgly.LCS = function(x, y) {
|
||||
this.x = x.replace(/[ ]{1}/g, '\n');
|
||||
this.y = y.replace(/[ ]{1}/g, '\n');
|
||||
this.x = (x && x.replace(/[ ]{1}/g, '\n')) || '';
|
||||
this.y = (y && y.replace(/[ ]{1}/g, '\n')) || '';
|
||||
};
|
||||
|
||||
jQuery.extend(Mgly.LCS.prototype, {
|
||||
@@ -461,11 +449,11 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
lineNumbers: this.settings.line_numbers
|
||||
};
|
||||
var lhs_gutters = [];
|
||||
if (this.lhs_cmsettings.line_numbers) {
|
||||
if (this.lhs_cmsettings.lineNumbers) {
|
||||
lhs_gutters = ['merge', 'CodeMirror-linenumbers']
|
||||
}
|
||||
var rhs_gutters = [];
|
||||
if (this.rhs_cmsettings.line_numbers) {
|
||||
if (this.rhs_cmsettings.lineNumbers) {
|
||||
rhs_gutters = ['merge', 'CodeMirror-linenumbers']
|
||||
}
|
||||
jQuery.extend(true, this.lhs_cmsettings, this.settings.cmsettings, { gutters: lhs_gutters }, this.settings);
|
||||
@@ -659,6 +647,13 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
bind: function(el) {
|
||||
this.element.hide();
|
||||
this.id = jQuery(el).attr('id');
|
||||
try {
|
||||
// ensure the id is valid for jQuery
|
||||
jQuery(`#${this.id}`);
|
||||
} catch (ex) {
|
||||
console.error(`jQuery failed to find mergely: #${this.id}`);
|
||||
return;
|
||||
}
|
||||
this.changed_timeout = null;
|
||||
this.chfns = {};
|
||||
this.chfns[this.id + '-lhs'] = [];
|
||||
@@ -676,7 +671,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
}
|
||||
else {
|
||||
// homebrew
|
||||
var style = 'opacity:0.4;width:10px;height:15px;background-color:#888;cursor:pointer;text-align:center;color:#eee;border:1px solid #222;margin-right:5px;margin-top: -2px;';
|
||||
var style = 'opacity:0.6;height:16px;background-color:#bfbfbf;cursor:pointer;text-align:center;color:#eee;border:1px solid #848484;margin-right:5px;margin-top:-2px;';
|
||||
merge_lhs_button = '<div style="' + style + '" title="Merge left"><</div>';
|
||||
merge_rhs_button = '<div style="' + style + '" title="Merge right">></div>';
|
||||
}
|
||||
@@ -686,17 +681,32 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
// create the textarea and canvas elements
|
||||
var height = '10px';
|
||||
var width = '10px';
|
||||
this.element.append(jQuery('<div id="mergely-splash">'));
|
||||
this.element.append(jQuery('<div class="mergely-margin" style="height: ' + height + '"><canvas id="' + this.id + '-lhs-margin" width="8px" height="' + height + '"></canvas></div>'));
|
||||
this.element.append(jQuery('<div style="position:relative;width:' + width + '; height:' + height + '" id="' + this.id + '-editor-lhs" class="mergely-column"><textarea style="" id="' + this.id + '-lhs"></textarea></div>'));
|
||||
this.element.append(jQuery('<div class="mergely-canvas" style="height: ' + height + '"><canvas id="' + this.id + '-lhs-' + this.id + '-rhs-canvas" style="width:28px" width="28px" height="' + height + '"></canvas></div>'));
|
||||
var rmargin = jQuery('<div class="mergely-margin" style="height: ' + height + '"><canvas id="' + this.id + '-rhs-margin" width="8px" height="' + height + '"></canvas></div>');
|
||||
|
||||
var splash = jQuery('<div id="mergely-splash">');
|
||||
var canvasLhs = jQuery(`<div class="mergely-margin" style="height: '${height}'"><canvas id="lhs-margin" width="8px" height="'${height}'"></canvas></div>`);
|
||||
canvasLhs.find('#lhs-margin').attr('id', `${this.id}-lhs-margin`);
|
||||
var editorLhs = jQuery(`<div style="position:relative;width:'${width}'; height:'${height}'" id="editor-lhs" class="mergely-column"><textarea id="text-lhs"></textarea></div>`);
|
||||
editorLhs.eq(0).attr('id', `${this.id}-editor-lhs`);
|
||||
editorLhs.find('#text-lhs').attr('id', `${this.id}-lhs`);
|
||||
var canvasMid = jQuery(`<div class="mergely-canvas" style="height: '${height}'"><canvas id="lhs-rhs-canvas" style="width:28px" width="28px" height="'${height}'"></canvas></div>`);
|
||||
canvasMid.find('#mergely-canvas').attr('id', `${this.id}-mergely-canvas`);
|
||||
canvasMid.find('#lhs-rhs-canvas').attr('id', `${this.id}-lhs-${this.id}-rhs-canvas`);
|
||||
|
||||
this.element.append(splash);
|
||||
this.element.append(canvasLhs);
|
||||
this.element.append(editorLhs);
|
||||
this.element.append(canvasMid);
|
||||
var canvasRhs = jQuery(`<div class="mergely-margin" style="height: '${height}'"><canvas id="rhs-margin" width="8px" height="'${height}'"></canvas></div>`);
|
||||
canvasRhs.find('#rhs-margin').attr('id', `${this.id}-rhs-margin`);
|
||||
if (this.settings.rhs_margin == 'left') {
|
||||
this.element.append(rmargin);
|
||||
this.element.append(canvasRhs);
|
||||
}
|
||||
this.element.append(jQuery('<div style="width:' + width + '; height:' + height + '" id="' + this.id + '-editor-rhs" class="mergely-column"><textarea style="" id="' + this.id + '-rhs"></textarea></div>'));
|
||||
var editorRhs = jQuery(`<div style="width:'${width}'; height:'${height}'" id="editor-rhs" class="mergely-column"><textarea id="text-rhs"></textarea></div>`);
|
||||
editorRhs.eq(0).attr('id', `${this.id}-editor-rhs`);
|
||||
editorRhs.find('#text-rhs').attr('id', `${this.id}-rhs`);
|
||||
this.element.append(editorRhs);
|
||||
if (this.settings.rhs_margin != 'left') {
|
||||
this.element.append(rmargin);
|
||||
this.element.append(canvasRhs);
|
||||
}
|
||||
if (!this.settings.sidebar) {
|
||||
this.element.find('.mergely-margin').css({display: 'none'});
|
||||
@@ -729,37 +739,47 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
}).append('<p><img width="36" height="36" alt="mergely" src="' + icon + '" style="float:left;padding-right:10px;" />This software is a Combined Work using Mergely and is covered by the ' + lic + ' license. For the full license, see <a target="_blank" href="http://www.mergely.com">http://www.mergely.com/license.</a></p>');
|
||||
jQuery('body').one('click', function () {
|
||||
jQuery('#mergely-splash').fadeOut(100, 'linear', function () {
|
||||
this.remove();
|
||||
jQuery('#mergely-splash').remove();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// check initialization
|
||||
var rhstx;
|
||||
try {
|
||||
rhstx = this.element.find(`#${this.id}-rhs`).get(0);
|
||||
} catch (ex) {
|
||||
}
|
||||
if (!rhstx) {
|
||||
console.error('rhs textarea not defined - Mergely not initialized properly');
|
||||
return;
|
||||
}
|
||||
var lhstx;
|
||||
try {
|
||||
lhstx = this.element.find(`#${this.id}-lhs`).get(0);
|
||||
} catch (ex) {
|
||||
}
|
||||
if (!lhstx) {
|
||||
console.error('lhs textarea not defined - Mergely not initialized properly');
|
||||
return;
|
||||
}
|
||||
|
||||
// get current diff border color
|
||||
var color = jQuery('<div style="display:none" class="mergely current start" />').appendTo('body').css('border-top-color');
|
||||
this.current_diff_color = color;
|
||||
|
||||
// codemirror
|
||||
var cmstyle = '#' + this.id + ' .CodeMirror-gutter-text { padding: 5px 0 0 0; }' +
|
||||
'#' + this.id + ' .CodeMirror-lines pre, ' + '#' + this.id + ' .CodeMirror-gutter-text pre { line-height: 18px; }' +
|
||||
'.CodeMirror-linewidget { overflow: hidden; };';
|
||||
var cmstyle = `#${this.id} .CodeMirror-gutter-text { padding: 5px 0 0 0; }
|
||||
'#${this.id} .CodeMirror-lines pre, #${this.id} .CodeMirror-gutter-text pre { line-height: 18px; }
|
||||
'.CodeMirror-linewidget { overflow: hidden; };`;
|
||||
if (this.settings.autoresize) {
|
||||
cmstyle += this.id + ' .CodeMirror-scroll { height: 100%; overflow: auto; }';
|
||||
cmstyle += `${this.id} .CodeMirror-scroll { height: 100%; overflow: auto; }`;
|
||||
}
|
||||
// adjust the margin line height
|
||||
cmstyle += '\n.CodeMirror { line-height: 18px; }';
|
||||
jQuery('<style type="text/css">' + cmstyle + '</style>').appendTo('head');
|
||||
jQuery(`<style type="text/css">${cmstyle}</style>`).appendTo('head');
|
||||
|
||||
//bind
|
||||
var rhstx = this.element.find('#' + this.id + '-rhs').get(0);
|
||||
if (!rhstx) {
|
||||
console.error('rhs textarea not defined - Mergely not initialized properly');
|
||||
return;
|
||||
}
|
||||
var lhstx = this.element.find('#' + this.id + '-lhs').get(0);
|
||||
if (!rhstx) {
|
||||
console.error('lhs textarea not defined - Mergely not initialized properly');
|
||||
return;
|
||||
}
|
||||
// bind
|
||||
var self = this;
|
||||
this.editor = [];
|
||||
this.editor[this.id + '-lhs'] = CodeMirror.fromTextArea(lhstx, this.lhs_cmsettings);
|
||||
@@ -918,13 +938,13 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
else this.trace('scroll', 'not scrolling other side');
|
||||
|
||||
if (this.settings.autoupdate) {
|
||||
var timer = new Mgly.Timer();
|
||||
Timer.start();
|
||||
this._calculate_offsets(editor_name1, editor_name2, this.changes);
|
||||
this.trace('change', 'offsets time', timer.stop());
|
||||
this.trace('change', 'offsets time', Timer.stop());
|
||||
this._markup_changes(editor_name1, editor_name2, this.changes);
|
||||
this.trace('change', 'markup time', timer.stop());
|
||||
this.trace('change', 'markup time', Timer.stop());
|
||||
this._draw_diff(editor_name1, editor_name2, this.changes);
|
||||
this.trace('change', 'draw time', timer.stop());
|
||||
this.trace('change', 'draw time', Timer.stop());
|
||||
}
|
||||
this.trace('scroll', 'scrolled');
|
||||
}
|
||||
@@ -934,9 +954,9 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
var self = this;
|
||||
if (this.changed_timeout != null) clearTimeout(this.changed_timeout);
|
||||
this.changed_timeout = setTimeout(function(){
|
||||
var timer = new Mgly.Timer();
|
||||
Timer.start();
|
||||
self._changed(editor_name1, editor_name2);
|
||||
self.trace('change', 'total time', timer.stop());
|
||||
self.trace('change', 'total time', Timer.stop());
|
||||
}, this.settings.change_timeout);
|
||||
},
|
||||
_changed: function(editor_name1, editor_name2) {
|
||||
@@ -947,7 +967,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
var self = this, name, editor, fns, timer, i, change, l;
|
||||
|
||||
var clear_changes = function() {
|
||||
timer = new Mgly.Timer();
|
||||
Timer.start();
|
||||
for (i = 0, l = editor.lineCount(); i < l; ++i) {
|
||||
editor.removeLineClass(i, 'background');
|
||||
}
|
||||
@@ -961,7 +981,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
change.clear();
|
||||
}
|
||||
editor.clearGutter('merge');
|
||||
self.trace('change', 'clear time', timer.stop());
|
||||
self.trace('change', 'clear time', Timer.stop());
|
||||
};
|
||||
|
||||
for (name in this.editor) {
|
||||
@@ -997,23 +1017,23 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
_diff: function(editor_name1, editor_name2) {
|
||||
var lhs = this.editor[editor_name1].getValue();
|
||||
var rhs = this.editor[editor_name2].getValue();
|
||||
var timer = new Mgly.Timer();
|
||||
Timer.start();
|
||||
var d = new Mgly.diff(lhs, rhs, this.settings);
|
||||
this.trace('change', 'diff time', timer.stop());
|
||||
this.trace('change', 'diff time', Timer.stop());
|
||||
this.changes = Mgly.DiffParser(d.normal_form());
|
||||
this.trace('change', 'parse time', timer.stop());
|
||||
this.trace('change', 'parse time', Timer.stop());
|
||||
if (this._current_diff === undefined && this.changes.length) {
|
||||
// go to first difference on start-up
|
||||
this._current_diff = 0;
|
||||
this._scroll_to_change(this.changes[0]);
|
||||
}
|
||||
this.trace('change', 'scroll_to_change time', timer.stop());
|
||||
this.trace('change', 'scroll_to_change time', Timer.stop());
|
||||
this._calculate_offsets(editor_name1, editor_name2, this.changes);
|
||||
this.trace('change', 'offsets time', timer.stop());
|
||||
this.trace('change', 'offsets time', Timer.stop());
|
||||
this._markup_changes(editor_name1, editor_name2, this.changes);
|
||||
this.trace('change', 'markup time', timer.stop());
|
||||
this.trace('change', 'markup time', Timer.stop());
|
||||
this._draw_diff(editor_name1, editor_name2, this.changes);
|
||||
this.trace('change', 'draw time', timer.stop());
|
||||
this.trace('change', 'draw time', Timer.stop());
|
||||
},
|
||||
_parse_diff: function (editor_name1, editor_name2, diff) {
|
||||
this.trace('diff', 'diff results:\n', diff);
|
||||
@@ -1046,21 +1066,13 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
}
|
||||
return changes;
|
||||
},
|
||||
_get_viewport: function(editor_name1, editor_name2) {
|
||||
var lhsvp = this.editor[editor_name1].getViewport();
|
||||
var rhsvp = this.editor[editor_name2].getViewport();
|
||||
return {from: Math.min(lhsvp.from, rhsvp.from), to: Math.max(lhsvp.to, rhsvp.to)};
|
||||
_get_viewport_side: function(editor_name) {
|
||||
return this.editor[editor_name].getViewport();
|
||||
},
|
||||
_is_change_in_view: function(vp, change) {
|
||||
if (!this.settings.viewport) return true;
|
||||
if ((change['lhs-line-from'] < vp.from && change['lhs-line-to'] < vp.to) ||
|
||||
(change['lhs-line-from'] > vp.from && change['lhs-line-to'] > vp.to) ||
|
||||
(change['rhs-line-from'] < vp.from && change['rhs-line-to'] < vp.to) ||
|
||||
(change['rhs-line-from'] > vp.from && change['rhs-line-to'] > vp.to)) {
|
||||
// if the change is outside the viewport, skip
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
_is_change_in_view: function(side, vp, change) {
|
||||
return (change[`${side}-line-from`] >= vp.from && change[`${side}-line-from`] <= vp.to) ||
|
||||
(change[`${side}-line-to`] >= vp.from && change[`${side}-line-to`] <= vp.to) ||
|
||||
(vp.from >= change[`${side}-line-from`] && vp.to <= change[`${side}-line-to`]);
|
||||
},
|
||||
_set_top_offset: function (editor_name1) {
|
||||
// save the current scroll position of the editor
|
||||
@@ -1105,12 +1117,15 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
}
|
||||
var lhschc = this.editor[editor_name1].charCoords({line: 0});
|
||||
var rhschc = this.editor[editor_name2].charCoords({line: 0});
|
||||
var vp = this._get_viewport(editor_name1, editor_name2);
|
||||
var lhsvp = this._get_viewport_side(editor_name1);
|
||||
var rhsvp = this._get_viewport_side(editor_name2);
|
||||
|
||||
for (var i = 0; i < changes.length; ++i) {
|
||||
var change = changes[i];
|
||||
|
||||
if (!this.settings.sidebar && !this._is_change_in_view(vp, change)) {
|
||||
if (this.settings.viewport &&
|
||||
!this._is_change_in_view(lhsvp, 'lhs', change) &&
|
||||
!this._is_change_in_view(lhsvp, 'rhs', change)) {
|
||||
// if the change is outside the viewport, skip
|
||||
delete change['lhs-y-start'];
|
||||
delete change['lhs-y-end'];
|
||||
@@ -1205,11 +1220,18 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
var led = this.editor[editor_name1];
|
||||
var red = this.editor[editor_name2];
|
||||
var current_diff = this._current_diff;
|
||||
var lhsvp = this._get_viewport_side(editor_name1);
|
||||
var rhsvp = this._get_viewport_side(editor_name2);
|
||||
|
||||
var timer = new Mgly.Timer();
|
||||
Timer.start();
|
||||
led.operation(function() {
|
||||
for (var i = 0; i < changes.length; ++i) {
|
||||
var change = changes[i];
|
||||
if (!this._is_change_in_view('lhs', lhsvp, change)) {
|
||||
// if the change is outside the viewport, skip
|
||||
continue;
|
||||
}
|
||||
|
||||
var llf = change['lhs-line-from'] >= 0 ? change['lhs-line-from'] : 0;
|
||||
var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
|
||||
var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
|
||||
@@ -1252,24 +1274,22 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
led.setGutterMarker(llf, 'merge', rhs_button.get(0));
|
||||
}
|
||||
}
|
||||
});
|
||||
}.bind(this));
|
||||
|
||||
var vp = this._get_viewport(editor_name1, editor_name2);
|
||||
|
||||
this.trace('change', 'markup lhs-editor time', timer.stop());
|
||||
this.trace('change', 'markup lhs-editor time', Timer.stop());
|
||||
red.operation(function() {
|
||||
for (var i = 0; i < changes.length; ++i) {
|
||||
var change = changes[i];
|
||||
if (!this._is_change_in_view('rhs', rhsvp, change)) {
|
||||
// if the change is outside the viewport, skip
|
||||
continue;
|
||||
}
|
||||
|
||||
var llf = change['lhs-line-from'] >= 0 ? change['lhs-line-from'] : 0;
|
||||
var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
|
||||
var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
|
||||
var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
|
||||
|
||||
if (!self._is_change_in_view(vp, change)) {
|
||||
// if the change is outside the viewport, skip
|
||||
continue;
|
||||
}
|
||||
|
||||
var clazz = ['mergely', 'rhs', change['op'], 'cid-' + i];
|
||||
red.addLineClass(rlf, 'background', 'start');
|
||||
red.addLineClass(rlt, 'background', 'end');
|
||||
@@ -1307,8 +1327,8 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
red.setGutterMarker(rlf, 'merge', lhs_button.get(0));
|
||||
}
|
||||
}
|
||||
});
|
||||
this.trace('change', 'markup rhs-editor time', timer.stop());
|
||||
}.bind(this));
|
||||
this.trace('change', 'markup rhs-editor time', Timer.stop());
|
||||
|
||||
// mark text deleted, LCS changes
|
||||
var marktext = [], i, j, k, p;
|
||||
@@ -1319,17 +1339,17 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
|
||||
var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
|
||||
|
||||
if (!this._is_change_in_view(vp, change)) {
|
||||
// if the change is outside the viewport, skip
|
||||
continue;
|
||||
}
|
||||
if (change['op'] == 'd') {
|
||||
// apply delete to cross-out (left-hand side only)
|
||||
var from = llf;
|
||||
var to = llt;
|
||||
var to_ln = led.lineInfo(to);
|
||||
if (to_ln) {
|
||||
marktext.push([led, {line:from, ch:0}, {line:to, ch:to_ln.text.length}, {className: 'mergely ch d lhs'}]);
|
||||
|
||||
if (this._is_change_in_view('lhs', lhsvp, change)) {
|
||||
// the change is within the viewport
|
||||
var to_ln = led.lineInfo(to);
|
||||
if (to_ln) {
|
||||
marktext.push([led, {line:from, ch:0}, {line:to, ch:to_ln.text.length}, {className: 'mergely ch d lhs'}]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (change['op'] == 'c') {
|
||||
@@ -1338,13 +1358,13 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
((j >= 0) && (j <= llt)) || ((k >= 0) && (k <= rlt));
|
||||
++j, ++k) {
|
||||
var lhs_line, rhs_line;
|
||||
if (k + p > rlt) {
|
||||
if (k + p > rlt && this._is_change_in_view('lhs', lhsvp, change)) {
|
||||
// lhs continues past rhs, mark lhs as deleted
|
||||
lhs_line = led.getLine( j );
|
||||
marktext.push([led, {line:j, ch:0}, {line:j, ch:lhs_line.length}, {className: 'mergely ch d lhs'}]);
|
||||
continue;
|
||||
}
|
||||
if (j + p > llt) {
|
||||
if (j + p > llt && this._is_change_in_view('rhs', rhsvp, change)) {
|
||||
// rhs continues past lhs, mark rhs as added
|
||||
rhs_line = red.getLine( k );
|
||||
marktext.push([red, {line:k, ch:0}, {line:k, ch:rhs_line.length}, {className: 'mergely ch a rhs'}]);
|
||||
@@ -1355,16 +1375,20 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
var lcs = new Mgly.LCS(lhs_line, rhs_line);
|
||||
lcs.diff(
|
||||
function added (from, to) {
|
||||
marktext.push([red, {line:k, ch:from}, {line:k, ch:to}, {className: 'mergely ch a rhs'}]);
|
||||
if (self._is_change_in_view('rhs', rhsvp, change)) {
|
||||
marktext.push([red, {line:k, ch:from}, {line:k, ch:to}, {className: 'mergely ch a rhs'}]);
|
||||
}
|
||||
},
|
||||
function removed (from, to) {
|
||||
marktext.push([led, {line:j, ch:from}, {line:j, ch:to}, {className: 'mergely ch d lhs'}]);
|
||||
if (self._is_change_in_view('lhs', lhsvp, change)) {
|
||||
marktext.push([led, {line:j, ch:from}, {line:j, ch:to}, {className: 'mergely ch d lhs'}]);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.trace('change', 'LCS marktext time', timer.stop());
|
||||
this.trace('change', 'LCS marktext time', Timer.stop());
|
||||
|
||||
// mark changes outside closure
|
||||
led.operation(function() {
|
||||
@@ -1384,7 +1408,7 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
}
|
||||
});
|
||||
|
||||
this.trace('change', 'LCS markup time', timer.stop());
|
||||
this.trace('change', 'LCS markup time', Timer.stop());
|
||||
|
||||
// merge buttons
|
||||
var ed = {lhs:led, rhs:red};
|
||||
@@ -1413,34 +1437,42 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
return false;
|
||||
});
|
||||
|
||||
// gutter markup
|
||||
var lhsLineNumbers = jQuery('#mergely-lhs ~ .CodeMirror').find('.CodeMirror-linenumber');
|
||||
var rhsLineNumbers = jQuery('#mergely-rhs ~ .CodeMirror').find('.CodeMirror-linenumber');
|
||||
// gutter markup that highlights all gutter line numbers for the current change.
|
||||
// cm doesn't give us the ability to style the line numbers directly.
|
||||
var lhsLineNumbers = jQuery('#mergely-lhs ~ .CodeMirror .CodeMirror-code .CodeMirror-linenumber.CodeMirror-gutter-elt');
|
||||
var rhsLineNumbers = jQuery('#mergely-rhs ~ .CodeMirror .CodeMirror-code .CodeMirror-linenumber.CodeMirror-gutter-elt');
|
||||
var jf, jt, i, j;
|
||||
rhsLineNumbers.removeClass('mergely current');
|
||||
lhsLineNumbers.removeClass('mergely current');
|
||||
for (var i = 0; i < changes.length; ++i) {
|
||||
if (current_diff == i && change.op !== 'd') {
|
||||
var change = changes[i];
|
||||
var j, jf = change['rhs-line-from'], jt = change['rhs-line-to'] + 1;
|
||||
for (j = jf; j < jt; j++) {
|
||||
var n = (j + 1).toString();
|
||||
rhsLineNumbers
|
||||
.filter(function(i, node) { return jQuery(node).text() === n; })
|
||||
.addClass('mergely current');
|
||||
var lhsvpFrom = parseInt(lhsLineNumbers.eq(0).text(), 10) - 1;
|
||||
var lhsvpTo = parseInt(lhsLineNumbers.eq(lhsLineNumbers.length - 1).text(), 10);
|
||||
var rhsvpFrom = parseInt(rhsLineNumbers.eq(0).text(), 10) - 1;
|
||||
var rhsvpTo = parseInt(rhsLineNumbers.eq(rhsLineNumbers.length - 1).text(), 10);
|
||||
|
||||
for (i = 0; i < changes.length; ++i) {
|
||||
change = changes[i];
|
||||
|
||||
if (current_diff == i && change.op !== 'a') {
|
||||
jf = change['lhs-line-from']
|
||||
jt = change['lhs-line-to'] + 1;
|
||||
for (j = jf; j < jt; ++j) {
|
||||
if (j >= lhsvpFrom && j <= lhsvpTo) {
|
||||
lhsLineNumbers.eq(j - lhsvpFrom).addClass('mergely current');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (current_diff == i && change.op !== 'a') {
|
||||
var change = changes[i];
|
||||
jf = change['lhs-line-from'], jt = change['lhs-line-to'] + 1;
|
||||
for (j = jf; j < jt; j++) {
|
||||
var n = (j + 1).toString();
|
||||
lhsLineNumbers.filter(function(i, node) { return jQuery(node).text() === n; })
|
||||
.addClass('mergely current');
|
||||
if (current_diff == i && change.op !== 'd') {
|
||||
jf = change['rhs-line-from']
|
||||
jt = change['rhs-line-to'] + 1;
|
||||
for (j = jf; j < jt; ++j) {
|
||||
if (j >= rhsvpFrom && j <= rhsvpTo) {
|
||||
rhsLineNumbers.eq(j - rhsvpFrom).addClass('mergely current');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.trace('change', 'markup buttons time', timer.stop());
|
||||
this.trace('change', 'markup buttons time', Timer.stop());
|
||||
},
|
||||
_merge_change : function(change, side, oside) {
|
||||
if (!change) return;
|
||||
@@ -1538,7 +1570,9 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
ctx_rhs.fillRect(0, 0, 6.5, ex.visible_page_height);
|
||||
ctx_rhs.strokeRect(0, 0, 6.5, ex.visible_page_height);
|
||||
|
||||
var vp = this._get_viewport(editor_name1, editor_name2);
|
||||
var lhsvp = this._get_viewport_side(editor_name1);
|
||||
var rhsvp = this._get_viewport_side(editor_name2);
|
||||
|
||||
for (var i = 0; i < changes.length; ++i) {
|
||||
var change = changes[i];
|
||||
var fill = this.settings.fgcolor[change['op']];
|
||||
@@ -1568,7 +1602,9 @@ jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
|
||||
ctx_rhs.fillRect(1.5, rhs_y_start, 4.5, Math.max(rhs_y_end - rhs_y_start, 5));
|
||||
ctx_rhs.strokeRect(1.5, rhs_y_start, 4.5, Math.max(rhs_y_end - rhs_y_start, 5));
|
||||
|
||||
if (!this._is_change_in_view(vp, change)) {
|
||||
if (!this._is_change_in_view('lhs', lhsvp, change) &&
|
||||
!this._is_change_in_view('rhs', rhsvp, change)) {
|
||||
// if the change is outside the viewport, skip
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
3412
tests/data/macbeth.js
Normal file
3412
tests/data/macbeth.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
const jQuery = require('jquery');
|
||||
const CodeMirror = require('CodeMirror');
|
||||
const mergely = require('../src/mergely');
|
||||
const macbeth = require('./data/macbeth').join('\n');
|
||||
const $ = jQuery;
|
||||
|
||||
(function($) {
|
||||
@@ -19,9 +20,10 @@ describe('mergely', function () {
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
$('#mergely').mergely('unbind');
|
||||
$('#mergely').mergelyUnregister();
|
||||
$('#mergely').remove();
|
||||
const mergely = $('#mergely');
|
||||
mergely.mergely('unbind');
|
||||
mergely.mergelyUnregister();
|
||||
mergely.remove();
|
||||
});
|
||||
|
||||
describe('initialization', () => {
|
||||
@@ -400,6 +402,7 @@ describe('mergely', function () {
|
||||
for (let i = 0; i < opt.next; ++i) {
|
||||
$('#mergely').mergely('scrollToDiff', 'next');
|
||||
}
|
||||
expect($('.merge-button').length > 0).to.be.true;
|
||||
$('#mergely').mergely('mergeCurrentChange', opt.dir);
|
||||
if (opt.dir === 'lhs') {
|
||||
expect($('#mergely').mergely('get', 'lhs')).to.equal(opt.expect || opt.rhs);
|
||||
@@ -414,4 +417,139 @@ describe('mergely', function () {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('_is_change_in_view', () => {
|
||||
it('should be false when change less-than viewport', function (done) {
|
||||
$(document).ready(() => {
|
||||
const editor = init({
|
||||
height: 100,
|
||||
viewport: true,
|
||||
license: 'lgpl-separate-notice',
|
||||
lhs: (setValue) => setValue(macbeth),
|
||||
rhs: (setValue) => setValue(macbeth)
|
||||
});
|
||||
const { mergely } = $('#mergely');
|
||||
expect($('#mergely').mergely('_is_change_in_view', 'lhs', {from: 10, to: 20}, {
|
||||
'lhs-line-from': 0,
|
||||
'lhs-line-to': 9
|
||||
})).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should be true when change less-than-equal viewport', function (done) {
|
||||
$(document).ready(() => {
|
||||
const editor = init({
|
||||
height: 100,
|
||||
viewport: true,
|
||||
license: 'lgpl-separate-notice',
|
||||
lhs: (setValue) => setValue(macbeth),
|
||||
rhs: (setValue) => setValue(macbeth)
|
||||
});
|
||||
const { mergely } = $('#mergely');
|
||||
expect($('#mergely').mergely('_is_change_in_view', 'lhs', {from: 10, to: 20}, {
|
||||
'lhs-line-from': 0,
|
||||
'lhs-line-to': 10
|
||||
})).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should be false when change greater-than viewport', function (done) {
|
||||
$(document).ready(() => {
|
||||
const editor = init({
|
||||
height: 100,
|
||||
viewport: true,
|
||||
license: 'lgpl-separate-notice',
|
||||
lhs: (setValue) => setValue(macbeth),
|
||||
rhs: (setValue) => setValue(macbeth)
|
||||
});
|
||||
const { mergely } = $('#mergely');
|
||||
expect($('#mergely').mergely('_is_change_in_view', 'lhs', {from: 10, to: 20}, {
|
||||
'lhs-line-from': 21,
|
||||
'lhs-line-to': 22
|
||||
})).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should be true when change straddles viewport from', function (done) {
|
||||
$(document).ready(() => {
|
||||
const editor = init({
|
||||
height: 100,
|
||||
viewport: true,
|
||||
license: 'lgpl-separate-notice',
|
||||
lhs: (setValue) => setValue(macbeth),
|
||||
rhs: (setValue) => setValue(macbeth)
|
||||
});
|
||||
const { mergely } = $('#mergely');
|
||||
expect($('#mergely').mergely('_is_change_in_view', 'lhs', {from: 10, to: 20}, {
|
||||
'lhs-line-from': 5,
|
||||
'lhs-line-to': 11
|
||||
})).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should be true when change straddles viewport to', function (done) {
|
||||
$(document).ready(() => {
|
||||
const editor = init({
|
||||
height: 100,
|
||||
viewport: true,
|
||||
license: 'lgpl-separate-notice',
|
||||
lhs: (setValue) => setValue(macbeth),
|
||||
rhs: (setValue) => setValue(macbeth)
|
||||
});
|
||||
const { mergely } = $('#mergely');
|
||||
expect($('#mergely').mergely('_is_change_in_view', 'lhs', {from: 10, to: 20}, {
|
||||
'lhs-line-from': 15,
|
||||
'lhs-line-to': 21
|
||||
})).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should be true when change encompasses viewport', function (done) {
|
||||
$(document).ready(() => {
|
||||
const editor = init({
|
||||
height: 100,
|
||||
viewport: true,
|
||||
license: 'lgpl-separate-notice',
|
||||
lhs: (setValue) => setValue(macbeth),
|
||||
rhs: (setValue) => setValue(macbeth)
|
||||
});
|
||||
const { mergely } = $('#mergely');
|
||||
expect($('#mergely').mergely('_is_change_in_view', 'lhs', {from: 10, to: 20}, {
|
||||
'lhs-line-from': 0,
|
||||
'lhs-line-to': 25
|
||||
})).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should not be vulnerable to XSS', function (done) {
|
||||
function initXSS(options) {
|
||||
$('body').get(0).innerHTML = "<!DOCTYPE html><html lang=\"en\"><body><div id='mergely<script id=\"injected\">alert(123)</script>'></div></body></html>";
|
||||
const divs = document.getElementsByTagName('div');
|
||||
editor = $(divs[0]);
|
||||
editor.mergely(options);
|
||||
return editor;
|
||||
};
|
||||
|
||||
$(document).ready(() => {
|
||||
const editor = initXSS({
|
||||
height: 100,
|
||||
viewport: true,
|
||||
license: 'lgpl-separate-notice',
|
||||
lhs: (setValue) => setValue(macbeth),
|
||||
rhs: (setValue) => setValue(macbeth)
|
||||
});
|
||||
expect($('body').find('#injected')).to.have.length(0, 'expected no div with id injected');
|
||||
const divs = document.getElementsByTagName('div');
|
||||
expect(divs).to.have.length(1);
|
||||
expect(divs[0].id).to.equal('mergely<script id="injected">alert(123)</script>');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
mergely: './src/mergely.js',
|
||||
// 'mergely.min': './src/mergely.js'
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, 'lib'),
|
||||
filename: './[name].js',
|
||||
library: 'mergely',
|
||||
libraryTarget: 'umd',
|
||||
umdNamedDefine: true
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('css-loader') }
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js']
|
||||
},
|
||||
externals: {
|
||||
jquery: 'jQuery',
|
||||
CodeMirror: 'CodeMirror'
|
||||
},
|
||||
plugins: [
|
||||
// new webpack.optimize.UglifyJsPlugin({
|
||||
// sourceMap: true,
|
||||
// include: /\.js$/,
|
||||
// // include: /\.min\.js$/,
|
||||
// exclude: /node_modules/
|
||||
// }),
|
||||
new ExtractTextPlugin('mergely.css')
|
||||
]
|
||||
};
|
||||
80
webpack.dev.js
Normal file
80
webpack.dev.js
Normal file
@@ -0,0 +1,80 @@
|
||||
const webpack = require('webpack')
|
||||
const path = require('path')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
mode: 'development',
|
||||
|
||||
module: {
|
||||
rules: [{
|
||||
include: [
|
||||
path.resolve(__dirname, 'src'),
|
||||
path.resolve(__dirname, 'examples')
|
||||
],
|
||||
test: /\.js$/
|
||||
}, {
|
||||
test: /\.(js)$/,
|
||||
exclude: /node_modules/,
|
||||
use: ['babel-loader']
|
||||
}, {
|
||||
test: /\.css$/,
|
||||
use: [{
|
||||
loader: 'style-loader',
|
||||
options: {
|
||||
sourceMap: true
|
||||
}
|
||||
}, {
|
||||
loader: 'css-loader'
|
||||
}]
|
||||
}]
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['.js'],
|
||||
alias: {
|
||||
'CodeMirror': path.join(__dirname, 'node_modules', 'codemirror'),
|
||||
'jQuery': path.join(__dirname, 'node_modules', 'jquery')
|
||||
}
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'examples/app.html',
|
||||
filename: 'mergely.html'
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
$: 'jquery',
|
||||
jQuery: 'jquery'
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
CodeMirror: 'codemirror'
|
||||
})
|
||||
],
|
||||
|
||||
entry: {
|
||||
app: [
|
||||
'./examples/app',
|
||||
'./src/mergely',
|
||||
]
|
||||
},
|
||||
|
||||
output: {
|
||||
filename: 'mergely.js',
|
||||
},
|
||||
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
vendors: {
|
||||
priority: -10,
|
||||
test: /[\\/]node_modules[\\/]/
|
||||
}
|
||||
},
|
||||
|
||||
chunks: 'async',
|
||||
minChunks: 1,
|
||||
minSize: 30000,
|
||||
name: true
|
||||
}
|
||||
}
|
||||
}
|
||||
38
webpack.prod.js
Normal file
38
webpack.prod.js
Normal file
@@ -0,0 +1,38 @@
|
||||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: {
|
||||
mergely: './src/mergely.js',
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, 'lib'),
|
||||
filename: './[name].js',
|
||||
library: 'mergely',
|
||||
libraryTarget: 'umd',
|
||||
umdNamedDefine: true
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.(js)$/,
|
||||
exclude: /node_modules/,
|
||||
use: ['babel-loader']
|
||||
}]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js']
|
||||
},
|
||||
externals: {
|
||||
jquery: 'jQuery',
|
||||
CodeMirror: 'CodeMirror'
|
||||
},
|
||||
plugins: [
|
||||
new CopyWebpackPlugin([{
|
||||
from: 'src/mergely.css',
|
||||
to: 'mergely.css',
|
||||
toType: 'file'
|
||||
}])
|
||||
]
|
||||
};
|
||||
Reference in New Issue
Block a user